diff --git a/jdk/make/sun/osxapp/Makefile b/jdk/make/sun/osxapp/Makefile index 7c47edd2d16..cb90f3eee61 100644 --- a/jdk/make/sun/osxapp/Makefile +++ b/jdk/make/sun/osxapp/Makefile @@ -28,6 +28,11 @@ LIBRARY = osxapp PRODUCT = sun include $(BUILDDIR)/common/Defs.gmk +GEN_DIR=$(GENSRCDIR)/sun/osxapp +ICON_DATA = $(GEN_DIR)/AWTIconData.h + +CLASSES_INIT += $(ICON_DATA) + # # Files # @@ -63,6 +68,7 @@ OTHER_LDLIBS += \ -framework QuartzCore CPPFLAGS += \ + -I$(GEN_DIR) \ $(call NativeSrcDirList,-I,/native/sun/osxapp) @@ -70,6 +76,34 @@ ifeq ($(MILESTONE), internal) CPPFLAGS += -DINTERNAL_BUILD endif -clean clobber:: +TEMPDIR_CLASSES = $(TEMPDIR)/classes -.PHONY: +$(TEMPDIR_CLASSES)/sun/osxapp/ToBin.class: ToBin.java + @$(prep-target) + $(BOOT_JAVAC_CMD) -d $(TEMPDIR_CLASSES) $< + +ifdef OPENJDK + ICONS_PATH_PREFIX=$(PLATFORM_SRC_MACOS) +else + ICONS_PATH_PREFIX=$(CLOSED_SRC)/macosx +endif + +generated.clean: + $(RM) -r $(GEN_DIR)/*.h + +ICONPATH=$(ICONS_PATH_PREFIX)/native/sun/osxapp/resource/icons +ICON = $(ICONPATH)/JavaApp.icns + +$(GEN_DIR)/AWTIconData.h: $(TEMPDIR_CLASSES)/sun/osxapp/ToBin.class $(ICON) + $(prep-target) + $(RM) $(ICON_DATA) + $(ECHO) "static unsigned char sAWTIconData[] = { " >> $(ICON_DATA); \ + $(CAT) $(ICON) | \ + $(BOOT_JAVA_CMD) -cp $(TEMPDIR_CLASSES) -Djava.awt.headless=true \ + sun.osxapp.ToBin >> $(ICON_DATA); \ + $(ECHO) "};" >> $(ICON_DATA); + + +clean clobber:: generated.clean + +.PHONY: generated.clean diff --git a/jdk/make/sun/osxapp/ToBin.java b/jdk/make/sun/osxapp/ToBin.java new file mode 100644 index 00000000000..9fdcba32b79 --- /dev/null +++ b/jdk/make/sun/osxapp/ToBin.java @@ -0,0 +1,50 @@ +/* + * 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. 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. + */ + +package sun.osxapp; + +import java.io.*; + +public class ToBin { + public static void main(String[] args) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int nRead; + byte[] data = new byte[4096]; + + while ((nRead = System.in.read(data, 0, data.length)) != -1) { + baos.write(data, 0, nRead); + } + + baos.flush(); + + byte[] buf = baos.toByteArray(); + for (int i = 0; i < buf.length; i++) { + System.out.print(String.format("0x%1$02X", buf[i]) + ", "); + if (i % 20 == 0) { + System.out.println(); + } + } + } +} diff --git a/jdk/src/macosx/classes/sun/lwawt/LWCanvasPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWCanvasPeer.java index e5d836288a5..f61b978d230 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWCanvasPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWCanvasPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -26,26 +26,27 @@ package sun.lwawt; +import java.awt.AWTException; import java.awt.BufferCapabilities; -import java.awt.Canvas; import java.awt.Component; +import java.awt.Dimension; import java.awt.GraphicsConfiguration; import java.awt.Image; import java.awt.peer.CanvasPeer; import javax.swing.JComponent; -final class LWCanvasPeer extends LWComponentPeer - implements CanvasPeer { +class LWCanvasPeer + extends LWComponentPeer implements CanvasPeer { - LWCanvasPeer(final Canvas target, PlatformComponent platformComponent) { + LWCanvasPeer(final T target, final PlatformComponent platformComponent) { super(target, platformComponent); } - // ---- PEER METHODS ---- // @Override - public void createBuffers(int numBuffers, BufferCapabilities caps) { + public void createBuffers(int numBuffers, BufferCapabilities caps) + throws AWTException { // TODO } @@ -67,10 +68,20 @@ final class LWCanvasPeer extends LWComponentPeer } @Override - public GraphicsConfiguration getAppropriateGraphicsConfiguration( + public final GraphicsConfiguration getAppropriateGraphicsConfiguration( GraphicsConfiguration gc) { // TODO return gc; } + + @Override + public final Dimension getPreferredSize() { + return getMinimumSize(); + } + + @Override + public final Dimension getMinimumSize() { + return getBounds().getSize(); + } } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWCheckboxPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWCheckboxPeer.java index 69bce89adae..de1c378b860 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWCheckboxPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWCheckboxPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -185,6 +185,11 @@ final class LWCheckboxPeer rb.setBounds(0, 0, w, h); } + @Override + public Dimension getPreferredSize() { + return getCurrentButton().getPreferredSize(); + } + @Override @Transient public Dimension getMinimumSize() { diff --git a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java index 1704b3bdd25..db6d2dd4430 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java @@ -123,7 +123,7 @@ public abstract class LWComponentPeer // private volatile boolean paintPending; private volatile boolean isLayouting; - private D delegate = null; + private final D delegate; private Container delegateContainer; private Component delegateDropTarget; private final Object dropTargetLock = new Object(); @@ -133,6 +133,11 @@ public abstract class LWComponentPeer private final PlatformComponent platformComponent; + /** + * Character with reasonable value between the minimum width and maximum. + */ + static final char WIDE_CHAR = '0'; + private final class DelegateContainer extends Container { { enableEvents(0xFFFFFFFF); @@ -267,9 +272,7 @@ public abstract class LWComponentPeer } protected final D getDelegate() { - synchronized (getStateLock()) { - return delegate; - } + return delegate; } protected Component getDelegateFocusOwner() { @@ -698,26 +701,23 @@ public abstract class LWComponentPeer } @Override - public FontMetrics getFontMetrics(Font f) { + public FontMetrics getFontMetrics(final Font f) { // Borrow the metrics from the top-level window // return getWindowPeer().getFontMetrics(f); // Obtain the metrics from the offscreen window where this peer is // mostly drawn to. // TODO: check for "use platform metrics" settings - Graphics g = getWindowPeer().getGraphics(); - try { - if (g != null) { + final Graphics g = getOnscreenGraphics(); + if (g != null) { + try { return g.getFontMetrics(f); - } else { - synchronized (getDelegateLock()) { - return delegateContainer.getFontMetrics(f); - } - } - } finally { - if (g != null) { + } finally { g.dispose(); } } + synchronized (getDelegateLock()) { + return delegateContainer.getFontMetrics(f); + } } @Override @@ -847,31 +847,46 @@ public abstract class LWComponentPeer } /** - * Should be overridden in subclasses to forward the request - * to the Swing helper component, if required. + * Determines the preferred size of the component. By default forwards the + * request to the Swing helper component. Should be overridden in subclasses + * if required. */ @Override public Dimension getPreferredSize() { - // It looks like a default implementation for all toolkits - return getMinimumSize(); + final Dimension size; + synchronized (getDelegateLock()) { + size = getDelegate().getPreferredSize(); + } + return validateSize(size); } - /* - * Should be overridden in subclasses to forward the request - * to the Swing helper component. + /** + * Determines the minimum size of the component. By default forwards the + * request to the Swing helper component. Should be overridden in subclasses + * if required. */ @Override public Dimension getMinimumSize() { - D delegate = getDelegate(); - - if (delegate == null) { - // Is it a correct default value? - return getBounds().getSize(); - } else { - synchronized (getDelegateLock()) { - return delegate.getMinimumSize(); - } + final Dimension size; + synchronized (getDelegateLock()) { + size = getDelegate().getMinimumSize(); } + return validateSize(size); + } + + /** + * In some situations delegates can return empty minimum/preferred size. + * (For example: empty JLabel, etc), but awt components never should be + * empty. In the XPeers or WPeers we use some magic constants, but here we + * try to use something more useful, + */ + private Dimension validateSize(final Dimension size) { + if (size.width == 0 || size.height == 0) { + final FontMetrics fm = getFontMetrics(getFont()); + size.width = fm.charWidth(WIDE_CHAR); + size.height = fm.getHeight(); + } + return size; } @Override diff --git a/jdk/src/macosx/classes/sun/lwawt/LWContainerPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWContainerPeer.java index dab0518754e..c213664b8ce 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWContainerPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWContainerPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -41,7 +41,7 @@ import java.util.List; import javax.swing.JComponent; abstract class LWContainerPeer - extends LWComponentPeer + extends LWCanvasPeer implements ContainerPeer { // List of child peers sorted by z-order from bottom-most diff --git a/jdk/src/macosx/classes/sun/lwawt/LWLabelPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWLabelPeer.java index f8c764364cc..19743da74a3 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWLabelPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWLabelPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -26,37 +26,26 @@ package sun.lwawt; -import java.awt.Dimension; -import java.awt.FontMetrics; import java.awt.Label; import java.awt.peer.LabelPeer; import javax.swing.JLabel; import javax.swing.SwingConstants; -import javax.tools.annotation.GenerateNativeHeader; - /** * Lightweight implementation of {@link LabelPeer}. Delegates most of the work * to the {@link JLabel}. */ -/* No native methods here, but the constants are needed in the supporting JNI code */ -@GenerateNativeHeader final class LWLabelPeer extends LWComponentPeer implements LabelPeer { - private static final int TEXT_XPAD = 5; - private static final int TEXT_YPAD = 1; - LWLabelPeer(final Label target, final PlatformComponent platformComponent) { super(target, platformComponent); } @Override protected JLabel createDelegate() { - final JLabel label = new JLabel(); - label.setVerticalAlignment(SwingConstants.TOP); - return label; + return new JLabel(); } @Override @@ -80,24 +69,6 @@ final class LWLabelPeer extends LWComponentPeer } } - @Override - public Dimension getMinimumSize() { - int w = TEXT_XPAD; - int h = TEXT_YPAD; - final FontMetrics fm = getFontMetrics(getFont()); - if (fm != null) { - final String text; - synchronized (getDelegateLock()) { - text = getDelegate().getText(); - } - if (text != null) { - w += fm.stringWidth(text); - } - h += fm.getHeight(); - } - return new Dimension(w, h); - } - /** * Converts {@code Label} alignment constant to the {@code JLabel} constant. * If wrong Label alignment provided returns default alignment. diff --git a/jdk/src/macosx/classes/sun/lwawt/LWListPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWListPeer.java index 1e6154fd64f..5edb8e16cd0 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWListPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWListPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -32,10 +32,22 @@ import java.awt.event.*; import java.awt.peer.ListPeer; import java.util.Arrays; -final class LWListPeer - extends LWComponentPeer +/** + * Lightweight implementation of {@link ListPeer}. + */ +final class LWListPeer extends LWComponentPeer implements ListPeer { + /** + * The default number of visible rows. + */ + private static final int DEFAULT_VISIBLE_ROWS = 4; // From java.awt.List, + + /** + * This text is used for cell bounds calculation. + */ + private static final String TEXT = "0123456789abcde"; + LWListPeer(final List target, final PlatformComponent platformComponent) { super(target, platformComponent); if (!getTarget().isBackgroundSet()) { @@ -134,6 +146,16 @@ final class LWListPeer } } + @Override + public Dimension getPreferredSize() { + return getMinimumSize(); + } + + @Override + public Dimension getMinimumSize() { + return getMinimumSize(DEFAULT_VISIBLE_ROWS); + } + @Override public Dimension getPreferredSize(final int rows) { return getMinimumSize(rows); @@ -142,18 +164,28 @@ final class LWListPeer @Override public Dimension getMinimumSize(final int rows) { synchronized (getDelegateLock()) { - final int margin = 2; - final int space = 1; - - // TODO: count ScrollPane's scrolling elements if any. - final FontMetrics fm = getFontMetrics(getFont()); - final int itemHeight = (fm.getHeight() - fm.getLeading()) + (2 * space); - - return new Dimension(20 + (fm == null ? 10 * 15 : fm.stringWidth("0123456789abcde")), - (fm == null ? 10 : itemHeight) * rows + (2 * margin)); + final Dimension size = getCellSize(); + size.height *= rows; + // Always take vertical scrollbar into account. + final JScrollBar vbar = getDelegate().getVerticalScrollBar(); + size.width += vbar != null ? vbar.getMinimumSize().width : 0; + // JScrollPane and JList insets + final Insets pi = getDelegate().getInsets(); + final Insets vi = getDelegate().getView().getInsets(); + size.width += pi.left + pi.right + vi.left + vi.right; + size.height += pi.top + pi.bottom + vi.top + vi.bottom; + return size; } } + private Dimension getCellSize() { + final JList jList = getDelegate().getView(); + final ListCellRenderer cr = jList.getCellRenderer(); + final Component cell = cr.getListCellRendererComponent(jList, TEXT, 0, + false, false); + return cell.getPreferredSize(); + } + private void revalidate() { synchronized (getDelegateLock()) { getDelegate().getView().invalidate(); @@ -165,10 +197,10 @@ final class LWListPeer private boolean skipStateChangedEvent; - private DefaultListModel model = - new DefaultListModel() { + private final DefaultListModel model = + new DefaultListModel() { @Override - public void add(final int index, final Object element) { + public void add(final int index, final String element) { if (index == -1) { addElement(element); } else { @@ -181,7 +213,7 @@ final class LWListPeer ScrollableJList() { getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE); - final JList list = new JListDelegate(); + final JList list = new JListDelegate(); list.addListSelectionListener(this); getViewport().setView(list); @@ -223,11 +255,11 @@ final class LWListPeer } } - public JList getView() { - return (JList) getViewport().getView(); + public JList getView() { + return (JList) getViewport().getView(); } - public DefaultListModel getModel() { + public DefaultListModel getModel() { return model; } @@ -254,7 +286,7 @@ final class LWListPeer } } - private final class JListDelegate extends JList { + private final class JListDelegate extends JList { JListDelegate() { super(ScrollableJList.this.model); @@ -272,7 +304,7 @@ final class LWListPeer final int index = locationToIndex(e.getPoint()); if (0 <= index && index < getModel().getSize()) { LWListPeer.this.postEvent(new ActionEvent(getTarget(), ActionEvent.ACTION_PERFORMED, - getModel().getElementAt(index).toString(), e.getWhen(), e.getModifiers())); + getModel().getElementAt(index), e.getWhen(), e.getModifiers())); } } } @@ -281,10 +313,10 @@ final class LWListPeer protected void processKeyEvent(final KeyEvent e) { super.processKeyEvent(e); if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_ENTER) { - final Object selectedValue = getSelectedValue(); + final String selectedValue = getSelectedValue(); if(selectedValue != null){ LWListPeer.this.postEvent(new ActionEvent(getTarget(), ActionEvent.ACTION_PERFORMED, - selectedValue.toString(), e.getWhen(), e.getModifiers())); + selectedValue, e.getWhen(), e.getModifiers())); } } } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWPanelPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWPanelPeer.java index 230cb89118e..6b1f48b08ad 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWPanelPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWPanelPeer.java @@ -26,7 +26,6 @@ package sun.lwawt; -import java.awt.Dimension; import java.awt.Panel; import java.awt.peer.PanelPeer; @@ -43,9 +42,4 @@ final class LWPanelPeer extends LWContainerPeer public JPanel createDelegate() { return new JPanel(); } - - @Override - public Dimension getMinimumSize() { - return getBounds().getSize(); - } } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWScrollBarPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWScrollBarPeer.java index 688f9e96f16..dff48a4caa3 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWScrollBarPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWScrollBarPeer.java @@ -27,7 +27,6 @@ package sun.lwawt; import java.awt.Adjustable; -import java.awt.Dimension; import java.awt.Scrollbar; import java.awt.event.AdjustmentEvent; import java.awt.event.AdjustmentListener; @@ -93,13 +92,6 @@ final class LWScrollBarPeer extends LWComponentPeer } } - @Override - public Dimension getPreferredSize() { - synchronized (getDelegateLock()) { - return getDelegate().getPreferredSize(); - } - } - // Peer also registered as a listener for ComponentDelegate component @Override public void adjustmentValueChanged(final AdjustmentEvent e) { diff --git a/jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java index 48467c19e2e..98032e20c29 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -29,6 +29,7 @@ package sun.lwawt; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; +import java.awt.Insets; import java.awt.Point; import java.awt.TextArea; import java.awt.event.TextEvent; @@ -41,11 +42,22 @@ import javax.swing.ScrollPaneConstants; import javax.swing.text.Document; import javax.swing.text.JTextComponent; +/** + * Lightweight implementation of {@link TextAreaPeer}. Delegates most of the + * work to the {@link JTextArea} inside JScrollPane. + */ final class LWTextAreaPeer extends LWTextComponentPeer implements TextAreaPeer { + /** + * The default number of visible columns. + */ private static final int DEFAULT_COLUMNS = 60; + + /** + * The default number of visible rows. + */ private static final int DEFAULT_ROWS = 10; LWTextAreaPeer(final TextArea target, @@ -86,27 +98,42 @@ final class LWTextAreaPeer return getTextComponent(); } + @Override + public Dimension getPreferredSize() { + return getMinimumSize(); + } + @Override public Dimension getMinimumSize() { return getMinimumSize(DEFAULT_ROWS, DEFAULT_COLUMNS); } @Override - public Dimension getMinimumSize(final int rows, final int columns) { - return getPreferredSize(rows, columns); + public Dimension getPreferredSize(final int rows, final int columns) { + return getMinimumSize(rows, columns); } @Override - public Dimension getPreferredSize(final int rows, final int columns) { - final Dimension size = super.getPreferredSize(rows, columns); + public Dimension getMinimumSize(final int rows, final int columns) { + final Dimension size = super.getMinimumSize(rows, columns); synchronized (getDelegateLock()) { - final JScrollBar vbar = getDelegate().getVerticalScrollBar(); - final JScrollBar hbar = getDelegate().getHorizontalScrollBar(); - final int scrollbarW = vbar != null ? vbar.getWidth() : 0; - final int scrollbarH = hbar != null ? hbar.getHeight() : 0; - return new Dimension(size.width + scrollbarW, - size.height + scrollbarH); + // JScrollPane insets + final Insets pi = getDelegate().getInsets(); + size.width += pi.left + pi.right; + size.height += pi.top + pi.bottom; + // Take scrollbars into account. + final int vsbPolicy = getDelegate().getVerticalScrollBarPolicy(); + if (vsbPolicy == ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS) { + final JScrollBar vbar = getDelegate().getVerticalScrollBar(); + size.width += vbar != null ? vbar.getMinimumSize().width : 0; + } + final int hsbPolicy = getDelegate().getHorizontalScrollBarPolicy(); + if (hsbPolicy == ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS) { + final JScrollBar hbar = getDelegate().getHorizontalScrollBar(); + size.height += hbar != null ? hbar.getMinimumSize().height : 0; + } } + return size; } @Override diff --git a/jdk/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java index 9db975da915..aab0baf43e0 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -48,10 +48,7 @@ abstract class LWTextComponentPeer implements DocumentListener, TextComponentPeer, InputMethodListener { - /** - * Character with reasonable value between the minimum width and maximum. - */ - protected static final char WIDE_CHAR = 'w'; + private volatile boolean firstChangeSkipped; LWTextComponentPeer(final T target, @@ -95,18 +92,16 @@ abstract class LWTextComponentPeer implements TextFieldPeer, ActionListener { - private static final int DEFAULT_COLUMNS = 1; - LWTextFieldPeer(final TextField target, final PlatformComponent platformComponent) { super(target, platformComponent); @@ -83,17 +77,12 @@ final class LWTextFieldPeer @Override public Dimension getPreferredSize(final int columns) { - return getPreferredSize(1, columns); + return getMinimumSize(columns); } @Override public Dimension getMinimumSize(final int columns) { - return getPreferredSize(columns); - } - - @Override - public Dimension getMinimumSize() { - return getMinimumSize(DEFAULT_COLUMNS); + return getMinimumSize(1, columns); } @Override diff --git a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java index 3c6ab83bcd6..cba6cec9c9f 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java @@ -310,7 +310,7 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { @Override public CanvasPeer createCanvas(Canvas target) { PlatformComponent platformComponent = createPlatformComponent(); - LWCanvasPeer peer = new LWCanvasPeer(target, platformComponent); + LWCanvasPeer peer = new LWCanvasPeer<>(target, platformComponent); targetCreatedPeer(target, peer); peer.initialize(); return peer; diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java index d874b26fb70..a7580a6f0cd 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java @@ -160,6 +160,9 @@ final class CPlatformResponder { if(isDeadChar){ testChar = (char) out[2]; + if(testChar == 0){ + return; + } } jkeyCode = out[0]; diff --git a/jdk/src/macosx/native/sun/awt/AWTEvent.m b/jdk/src/macosx/native/sun/awt/AWTEvent.m index 85c9fa9718e..7bde46f1709 100644 --- a/jdk/src/macosx/native/sun/awt/AWTEvent.m +++ b/jdk/src/macosx/native/sun/awt/AWTEvent.m @@ -383,6 +383,7 @@ static unichar NsGetDeadKeyChar(unsigned short keyCode) { TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); + if (uchr == nil) { return; } const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr); // Carbon modifiers should be used instead of NSEvent modifiers UInt32 modifierKeyState = (GetCurrentEventKeyModifiers() >> 8) & 0xFF; @@ -563,18 +564,18 @@ NSUInteger JavaModifiersToNsKeyModifiers(jint javaModifiers, BOOL isExtMods) const struct _nsKeyToJavaModifier* cur; for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) { - jint mask = isExtMods? cur->javaExtMask : cur->javaMask; + jint mask = isExtMods? cur->javaExtMask : cur->javaMask; if ((mask & javaModifiers) != 0) { nsFlags |= cur->nsMask; } } // special case - jint mask = isExtMods? java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK : + jint mask = isExtMods? java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK : java_awt_event_InputEvent_ALT_GRAPH_MASK; if ((mask & javaModifiers) != 0) { - nsFlags |= NSAlternateKeyMask; + nsFlags |= NSAlternateKeyMask; } return nsFlags; diff --git a/jdk/src/macosx/native/sun/awt/AWTView.m b/jdk/src/macosx/native/sun/awt/AWTView.m index 2d271777321..79219e4c55d 100644 --- a/jdk/src/macosx/native/sun/awt/AWTView.m +++ b/jdk/src/macosx/native/sun/awt/AWTView.m @@ -279,7 +279,10 @@ AWT_ASSERT_APPKIT_THREAD; return; } - if (![self hasMarkedText] && fKeyEventsNeeded) { + NSString *eventCharacters = [event characters]; + BOOL isDeadKey = (eventCharacters != nil && [eventCharacters length] == 0); + + if ((![self hasMarkedText] && fKeyEventsNeeded) || isDeadKey) { [self deliverJavaKeyEventHelper: event]; } diff --git a/jdk/src/macosx/native/sun/awt/InitIDs.m b/jdk/src/macosx/native/sun/awt/InitIDs.m index d8b0fdccf7d..2b1c007fd4c 100644 --- a/jdk/src/macosx/native/sun/awt/InitIDs.m +++ b/jdk/src/macosx/native/sun/awt/InitIDs.m @@ -47,7 +47,10 @@ JNIEXPORT void JNICALL Java_java_awt_CheckboxMenuItem_initIDs { } - +JNIEXPORT void JNICALL Java_java_awt_Choice_initIDs +(JNIEnv *env, jclass cls) +{ +} JNIEXPORT void JNICALL Java_java_awt_Color_initIDs (JNIEnv *env, jclass cls) diff --git a/jdk/src/macosx/native/sun/awt/LWCToolkit.m b/jdk/src/macosx/native/sun/awt/LWCToolkit.m index f9b17fca6b7..b58cfc0627d 100644 --- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m +++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m @@ -33,6 +33,7 @@ #import "ThreadUtilities.h" #import "AWT_debug.h" #import "CSystemColors.h" +#import "NSApplicationAWT.h" #import "sun_lwawt_macosx_LWCToolkit.h" @@ -47,7 +48,7 @@ static long eventCount; return eventCount; } -+ (void) eventCountPlusPlus{ ++ (void) eventCountPlusPlus{ eventCount++; } @@ -79,7 +80,6 @@ static long eventCount; @end - /* * Class: sun_lwawt_macosx_LWCToolkit * Method: nativeSyncQueue @@ -90,12 +90,22 @@ JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_nativeSyncQueue { int currentEventNum = [AWTToolkit getEventCount]; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){}]; - + NSApplication* sharedApp = [NSApplication sharedApplication]; + if ([sharedApp isKindOfClass:[NSApplicationAWT class]]) { + NSApplicationAWT* theApp = (NSApplicationAWT*)sharedApp; + [theApp postDummyEvent]; + [theApp waitForDummyEvent]; + } else { + // could happen if we are embedded inside SWT application, + // in this case just spin a single empty block through + // the event loop to give it a chance to process pending events + [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){}]; + } + if (([AWTToolkit getEventCount] - currentEventNum) != 0) { return JNI_TRUE; } - + return JNI_FALSE; } diff --git a/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.h b/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.h index 3f4bc0ca749..f8db314a314 100644 --- a/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.h +++ b/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.h @@ -29,11 +29,15 @@ @interface NSApplicationAWT : NSApplication { NSString *fApplicationName; NSWindow *eventTransparentWindow; + NSTimeInterval dummyEventTimestamp; + NSConditionLock* seenDummyEventLock; } - (void) finishLaunching; - (void) registerWithProcessManager; - (void) setDockIconWithEnv:(JNIEnv *)env; +- (void) postDummyEvent; +- (void) waitForDummyEvent; + (void) runAWTLoopWithApp:(NSApplication*)app; diff --git a/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m b/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m index bc18e00f1fc..5c3c5f3addb 100644 --- a/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m +++ b/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m @@ -31,6 +31,7 @@ #import "PropertiesUtilities.h" #import "ThreadUtilities.h" #import "QueuingApplicationDelegate.h" +#import "AWTIconData.h" static BOOL sUsingDefaultNIB = YES; @@ -52,6 +53,9 @@ BOOL postEventDuringEventSynthesis = NO; AWT_ASSERT_APPKIT_THREAD; fApplicationName = nil; + dummyEventTimestamp = 0.0; + seenDummyEventLock = nil; + // NSApplication will call _RegisterApplication with the application's bundle, but there may not be one. // So, we need to call it ourselves to ensure the app is set up properly. @@ -255,25 +259,26 @@ AWT_ASSERT_APPKIT_THREAD; theIconPath = [PropertiesUtilities javaSystemPropertyForKey:@"apple.awt.application.icon" withEnv:env]; } - // If the icon file wasn't specified as an argument and we need to get an icon - // we'll use the generic java app icon. - NSString *defaultIconPath = [NSString stringWithFormat:@"%@%@", SHARED_FRAMEWORK_BUNDLE, @"/Resources/GenericApp.icns"]; - if (theIconPath == nil) { + // Use the path specified to get the icon image + NSImage* iconImage = nil; + if (theIconPath != nil) { + iconImage = [[NSImage alloc] initWithContentsOfFile:theIconPath]; + } + + // If no icon file was specified or we failed to get the icon image + // and there is no bundle's icon, then use the default icon + if (iconImage == nil) { NSString* bundleIcon = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIconFile"]; if (bundleIcon == nil) { - theIconPath = defaultIconPath; + NSData* iconData; + iconData = [[NSData alloc] initWithBytesNoCopy: sAWTIconData length: sizeof(sAWTIconData) freeWhenDone: NO]; + iconImage = [[NSImage alloc] initWithData: iconData]; + [iconData release]; } } - // Set up the dock icon if we have an icon name. - if (theIconPath != nil) { - NSImage *iconImage = [[NSImage alloc] initWithContentsOfFile:theIconPath]; - - // If we failed for some reason fall back to the default icon. - if (iconImage == nil) { - iconImage = [[NSImage alloc] initWithContentsOfFile:defaultIconPath]; - } - + // Set up the dock icon if we have an icon image. + if (iconImage != nil) { [NSApp setApplicationIconImage:iconImage]; [iconImage release]; } @@ -328,6 +333,45 @@ AWT_ASSERT_APPKIT_THREAD; return event; } +// NSTimeInterval has microseconds precision +#define TS_EQUAL(ts1, ts2) (fabs((ts1) - (ts2)) < 1e-6) + +- (void)sendEvent:(NSEvent *)event +{ + if ([event type] == NSApplicationDefined && TS_EQUAL([event timestamp], dummyEventTimestamp)) { + [seenDummyEventLock lockWhenCondition:NO]; + [seenDummyEventLock unlockWithCondition:YES]; + } else { + [super sendEvent:event]; + } +} + +- (void)postDummyEvent { + seenDummyEventLock = [[NSConditionLock alloc] initWithCondition:NO]; + dummyEventTimestamp = [NSProcessInfo processInfo].systemUptime; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSEvent* event = [NSEvent otherEventWithType: NSApplicationDefined + location: NSMakePoint(0,0) + modifierFlags: 0 + timestamp: dummyEventTimestamp + windowNumber: 0 + context: nil + subtype: 0 + data1: 0 + data2: 0]; + [NSApp postEvent: event atStart: NO]; + [pool drain]; +} + +- (void)waitForDummyEvent { + [seenDummyEventLock lockWhenCondition:YES]; + [seenDummyEventLock unlock]; + [seenDummyEventLock release]; + + seenDummyEventLock = nil; +} + @end diff --git a/jdk/src/macosx/native/sun/osxapp/resource/icons/JavaApp.icns b/jdk/src/macosx/native/sun/osxapp/resource/icons/JavaApp.icns new file mode 100644 index 00000000000..fc60195cd0e Binary files /dev/null and b/jdk/src/macosx/native/sun/osxapp/resource/icons/JavaApp.icns differ diff --git a/jdk/src/share/classes/java/awt/Choice.java b/jdk/src/share/classes/java/awt/Choice.java index d7d55a24dc2..895be89a615 100644 --- a/jdk/src/share/classes/java/awt/Choice.java +++ b/jdk/src/share/classes/java/awt/Choice.java @@ -104,7 +104,16 @@ public class Choice extends Component implements ItemSelectable, Accessible { /* * JDK 1.1 serialVersionUID */ - private static final long serialVersionUID = -4075310674757313071L; + private static final long serialVersionUID = -4075310674757313071L; + + static { + /* ensure that the necessary native libraries are loaded */ + Toolkit.loadLibraries(); + /* initialize JNI field and method ids */ + if (!GraphicsEnvironment.isHeadless()) { + initIDs(); + } + } /** * Creates a new choice menu. The menu initially has no items in it. @@ -711,6 +720,10 @@ public class Choice extends Component implements ItemSelectable, Accessible { } } + /** + * Initialize JNI field and method IDs + */ + private static native void initIDs(); ///////////////// // Accessibility support diff --git a/jdk/src/share/classes/javax/swing/ToolTipManager.java b/jdk/src/share/classes/javax/swing/ToolTipManager.java index fd0953dd252..1bb26e29cce 100644 --- a/jdk/src/share/classes/javax/swing/ToolTipManager.java +++ b/jdk/src/share/classes/javax/swing/ToolTipManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -217,6 +217,25 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener return exitTimer.getInitialDelay(); } + // Returns GraphicsConfiguration instance that toFind belongs to or null + // if drawing point is set to a point beyond visible screen area (e.g. + // Point(20000, 20000)) + private GraphicsConfiguration getDrawingGC(Point toFind) { + GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice devices[] = env.getScreenDevices(); + for (GraphicsDevice device : devices) { + GraphicsConfiguration configs[] = device.getConfigurations(); + for (GraphicsConfiguration config : configs) { + Rectangle rect = config.getBounds(); + if (rect.contains(toFind)) { + return config; + } + } + } + + return null; + } + void showTipWindow() { if(insideComponent == null || !insideComponent.isShowing()) return; @@ -231,9 +250,25 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener if (enabled) { Dimension size; Point screenLocation = insideComponent.getLocationOnScreen(); - Point location = new Point(); - GraphicsConfiguration gc; - gc = insideComponent.getGraphicsConfiguration(); + Point location; + + Point toFind; + if (preferredLocation != null) { + toFind = new Point(screenLocation.x + preferredLocation.x, + screenLocation.y + preferredLocation.y); + } else { + toFind = mouseEvent.getLocationOnScreen(); + } + + GraphicsConfiguration gc = getDrawingGC(toFind); + if (gc == null) { + toFind = mouseEvent.getLocationOnScreen(); + gc = getDrawingGC(toFind); + if (gc == null) { + gc = insideComponent.getGraphicsConfiguration(); + } + } + Rectangle sBounds = gc.getBounds(); Insets screenInsets = Toolkit.getDefaultToolkit() .getScreenInsets(gc); @@ -253,14 +288,13 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener size = tip.getPreferredSize(); if(preferredLocation != null) { - location.x = screenLocation.x + preferredLocation.x; - location.y = screenLocation.y + preferredLocation.y; + location = toFind; if (!leftToRight) { location.x -= size.width; } } else { - location.x = screenLocation.x + mouseEvent.getX(); - location.y = screenLocation.y + mouseEvent.getY() + 20; + location = new Point(screenLocation.x + mouseEvent.getX(), + screenLocation.y + mouseEvent.getY() + 20); if (!leftToRight) { if(location.x - size.width>=0) { location.x -= size.width; diff --git a/jdk/src/share/classes/javax/swing/colorchooser/DefaultSwatchChooserPanel.java b/jdk/src/share/classes/javax/swing/colorchooser/DefaultSwatchChooserPanel.java index a0227dd716c..564a085ea98 100644 --- a/jdk/src/share/classes/javax/swing/colorchooser/DefaultSwatchChooserPanel.java +++ b/jdk/src/share/classes/javax/swing/colorchooser/DefaultSwatchChooserPanel.java @@ -57,6 +57,8 @@ class DefaultSwatchChooserPanel extends AbstractColorChooserPanel { RecentSwatchPanel recentSwatchPanel; MouseListener mainSwatchListener; MouseListener recentSwatchListener; + private KeyListener mainSwatchKeyListener; + private KeyListener recentSwatchKeyListener; public DefaultSwatchChooserPanel() { super(); @@ -151,10 +153,14 @@ class DefaultSwatchChooserPanel extends AbstractColorChooserPanel { recentSwatchPanel.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, recentStr); + mainSwatchKeyListener = new MainSwatchKeyListener(); mainSwatchListener = new MainSwatchListener(); swatchPanel.addMouseListener(mainSwatchListener); + swatchPanel.addKeyListener(mainSwatchKeyListener); recentSwatchListener = new RecentSwatchListener(); + recentSwatchKeyListener = new RecentSwatchKeyListener(); recentSwatchPanel.addMouseListener(recentSwatchListener); + recentSwatchPanel.addKeyListener(recentSwatchKeyListener); JPanel mainHolder = new JPanel(new BorderLayout()); Border border = new CompoundBorder( new LineBorder(Color.black), @@ -196,11 +202,17 @@ class DefaultSwatchChooserPanel extends AbstractColorChooserPanel { public void uninstallChooserPanel(JColorChooser enclosingChooser) { super.uninstallChooserPanel(enclosingChooser); swatchPanel.removeMouseListener(mainSwatchListener); + swatchPanel.removeKeyListener(mainSwatchKeyListener); recentSwatchPanel.removeMouseListener(recentSwatchListener); + recentSwatchPanel.removeKeyListener(recentSwatchKeyListener); + swatchPanel = null; recentSwatchPanel = null; mainSwatchListener = null; + mainSwatchKeyListener = null; recentSwatchListener = null; + recentSwatchKeyListener = null; + removeAll(); // strip out all the sub-components } @@ -209,11 +221,32 @@ class DefaultSwatchChooserPanel extends AbstractColorChooserPanel { } + private class RecentSwatchKeyListener extends KeyAdapter { + public void keyPressed(KeyEvent e) { + if (KeyEvent.VK_SPACE == e.getKeyCode()) { + Color color = recentSwatchPanel.getSelectedColor(); + setSelectedColor(color); + } + } + } + + private class MainSwatchKeyListener extends KeyAdapter { + public void keyPressed(KeyEvent e) { + if (KeyEvent.VK_SPACE == e.getKeyCode()) { + Color color = swatchPanel.getSelectedColor(); + setSelectedColor(color); + recentSwatchPanel.setMostRecentColor(color); + } + } + } + class RecentSwatchListener extends MouseAdapter implements Serializable { public void mousePressed(MouseEvent e) { if (isEnabled()) { Color color = recentSwatchPanel.getColorForLocation(e.getX(), e.getY()); + recentSwatchPanel.setSelectedColorFromLocation(e.getX(), e.getY()); setSelectedColor(color); + recentSwatchPanel.requestFocusInWindow(); } } } @@ -223,7 +256,9 @@ class DefaultSwatchChooserPanel extends AbstractColorChooserPanel { if (isEnabled()) { Color color = swatchPanel.getColorForLocation(e.getX(), e.getY()); setSelectedColor(color); + swatchPanel.setSelectedColorFromLocation(e.getX(), e.getY()); recentSwatchPanel.setMostRecentColor(color); + swatchPanel.requestFocusInWindow(); } } } @@ -239,18 +274,81 @@ class SwatchPanel extends JPanel { protected Dimension numSwatches; protected Dimension gap; + private int selRow; + private int selCol; + public SwatchPanel() { initValues(); initColors(); setToolTipText(""); // register for events setOpaque(true); setBackground(Color.white); - setRequestFocusEnabled(false); + setFocusable(true); setInheritsPopupMenu(true); + + addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + repaint(); + } + + public void focusLost(FocusEvent e) { + repaint(); + } + }); + + addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + int typed = e.getKeyCode(); + switch (typed) { + case KeyEvent.VK_UP: + if (selRow > 0) { + selRow--; + repaint(); + } + break; + case KeyEvent.VK_DOWN: + if (selRow < numSwatches.height - 1) { + selRow++; + repaint(); + } + break; + case KeyEvent.VK_LEFT: + if (selCol > 0 && SwatchPanel.this.getComponentOrientation().isLeftToRight()) { + selCol--; + repaint(); + } else if (selCol < numSwatches.width - 1 + && !SwatchPanel.this.getComponentOrientation().isLeftToRight()) { + selCol++; + repaint(); + } + break; + case KeyEvent.VK_RIGHT: + if (selCol < numSwatches.width - 1 + && SwatchPanel.this.getComponentOrientation().isLeftToRight()) { + selCol++; + repaint(); + } else if (selCol > 0 && !SwatchPanel.this.getComponentOrientation().isLeftToRight()) { + selCol--; + repaint(); + } + break; + case KeyEvent.VK_HOME: + selCol = 0; + selRow = 0; + repaint(); + break; + case KeyEvent.VK_END: + selCol = numSwatches.width - 1; + selRow = numSwatches.height - 1; + repaint(); + break; + } + } + }); } - public boolean isFocusTraversable() { - return false; + public Color getSelectedColor() { + return getColorForCell(selCol, selRow); } protected void initValues() { @@ -263,11 +361,10 @@ class SwatchPanel extends JPanel { for (int row = 0; row < numSwatches.height; row++) { int y = row * (swatchSize.height + gap.height); for (int column = 0; column < numSwatches.width; column++) { - - g.setColor( getColorForCell(column, row) ); + Color c = getColorForCell(column, row); + g.setColor(c); int x; - if ((!this.getComponentOrientation().isLeftToRight()) && - (this instanceof RecentSwatchPanel)) { + if (!this.getComponentOrientation().isLeftToRight()) { x = (numSwatches.width - column - 1) * (swatchSize.width + gap.width); } else { x = column * (swatchSize.width + gap.width); @@ -276,6 +373,20 @@ class SwatchPanel extends JPanel { g.setColor(Color.black); g.drawLine( x+swatchSize.width-1, y, x+swatchSize.width-1, y+swatchSize.height-1); g.drawLine( x, y+swatchSize.height-1, x+swatchSize.width-1, y+swatchSize.height-1); + + if (selRow == row && selCol == column && this.isFocusOwner()) { + Color c2 = new Color(c.getRed() < 125 ? 255 : 0, + c.getGreen() < 125 ? 255 : 0, + c.getBlue() < 125 ? 255 : 0); + g.setColor(c2); + + g.drawLine(x, y, x + swatchSize.width - 1, y); + g.drawLine(x, y, x, y + swatchSize.height - 1); + g.drawLine(x + swatchSize.width - 1, y, x + swatchSize.width - 1, y + swatchSize.height - 1); + g.drawLine(x, y + swatchSize.height - 1, x + swatchSize.width - 1, y + swatchSize.height - 1); + g.drawLine(x, y, x + swatchSize.width - 1, y + swatchSize.height - 1); + g.drawLine(x, y + swatchSize.height - 1, x + swatchSize.width - 1, y); + } } } } @@ -296,10 +407,19 @@ class SwatchPanel extends JPanel { return color.getRed()+", "+ color.getGreen() + ", " + color.getBlue(); } + public void setSelectedColorFromLocation(int x, int y) { + if (!this.getComponentOrientation().isLeftToRight()) { + selCol = numSwatches.width - x / (swatchSize.width + gap.width) - 1; + } else { + selCol = x / (swatchSize.width + gap.width); + } + selRow = y / (swatchSize.height + gap.height); + repaint(); + } + public Color getColorForLocation( int x, int y ) { int column; - if ((!this.getComponentOrientation().isLeftToRight()) && - (this instanceof RecentSwatchPanel)) { + if (!this.getComponentOrientation().isLeftToRight()) { column = numSwatches.width - x / (swatchSize.width + gap.width) - 1; } else { column = x / (swatchSize.width + gap.width); diff --git a/jdk/src/solaris/native/sun/awt/initIDs.c b/jdk/src/solaris/native/sun/awt/initIDs.c index 3bd1e68903c..3c9a388f95c 100644 --- a/jdk/src/solaris/native/sun/awt/initIDs.c +++ b/jdk/src/solaris/native/sun/awt/initIDs.c @@ -88,6 +88,12 @@ Java_java_awt_CheckboxMenuItem_initIDs { } +JNIEXPORT void JNICALL +Java_java_awt_Choice_initIDs + (JNIEnv *env, jclass clazz) +{ +} + JNIEXPORT void JNICALL Java_java_awt_Dimension_initIDs (JNIEnv *env, jclass clazz) diff --git a/jdk/src/windows/native/sun/windows/awt_Choice.cpp b/jdk/src/windows/native/sun/windows/awt_Choice.cpp index dfd9a6de6b3..5b9647fd7a7 100644 --- a/jdk/src/windows/native/sun/windows/awt_Choice.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Choice.cpp @@ -79,6 +79,10 @@ BOOL AwtChoice::sm_isMouseMoveInList = FALSE; static const UINT MINIMUM_NUMBER_OF_VISIBLE_ITEMS = 8; +namespace { + jfieldID selectedIndexID; +} + /************************************************************************* * AwtChoice class methods */ @@ -86,7 +90,6 @@ static const UINT MINIMUM_NUMBER_OF_VISIBLE_ITEMS = 8; AwtChoice::AwtChoice() { m_hList = NULL; m_listDefWindowProc = NULL; - m_selectedItem = -1; } LPCTSTR AwtChoice::GetClassName() { @@ -102,7 +105,6 @@ void AwtChoice::Dispose() { AwtChoice* AwtChoice::Create(jobject peer, jobject parent) { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); jobject target = NULL; @@ -438,10 +440,14 @@ LRESULT CALLBACK AwtChoice::ListWindowProc(HWND hwnd, UINT message, MsgRouting AwtChoice::WmNotify(UINT notifyCode) { if (notifyCode == CBN_SELCHANGE) { - int selectedItem = (int)SendMessage(CB_GETCURSEL); - if (selectedItem != CB_ERR && m_selectedItem != selectedItem){ - m_selectedItem = selectedItem; - DoCallback("handleAction", "(I)V", selectedItem); + int selectedIndex = (int)SendMessage(CB_GETCURSEL); + + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + jobject target = GetTarget(env); + int previousIndex = env->GetIntField(target, selectedIndexID); + + if (selectedIndex != CB_ERR && selectedIndex != previousIndex){ + DoCallback("handleAction", "(I)V", selectedIndex); } } else if (notifyCode == CBN_DROPDOWN) { @@ -695,6 +701,15 @@ done: extern "C" { +JNIEXPORT void JNICALL +Java_java_awt_Choice_initIDs(JNIEnv *env, jclass cls) +{ + TRY; + selectedIndexID = env->GetFieldID(cls, "selectedIndex", "I"); + DASSERT(selectedIndexID); + CATCH_BAD_ALLOC; +} + /* * Class: sun_awt_windows_WChoicePeer * Method: select diff --git a/jdk/src/windows/native/sun/windows/awt_Choice.h b/jdk/src/windows/native/sun/windows/awt_Choice.h index 194ae08bd1b..36be8d91aa5 100644 --- a/jdk/src/windows/native/sun/windows/awt_Choice.h +++ b/jdk/src/windows/native/sun/windows/awt_Choice.h @@ -94,7 +94,6 @@ private: static BOOL sm_isMouseMoveInList; HWND m_hList; WNDPROC m_listDefWindowProc; - int m_selectedItem; static LRESULT CALLBACK ListWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); }; diff --git a/jdk/src/windows/native/sun/windows/awt_Component.cpp b/jdk/src/windows/native/sun/windows/awt_Component.cpp index d7b265c44e3..d6c4e974e0f 100644 --- a/jdk/src/windows/native/sun/windows/awt_Component.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp @@ -3144,7 +3144,8 @@ void AwtComponent::JavaKeyToWindowsKey(UINT javaKey, return; } -UINT AwtComponent::WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers) +UINT AwtComponent::WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers, UINT character, BOOL isDeadKey) + { // Handle the few cases where we need to take the modifier into // consideration for the Java VK code or where we have to take the keyboard @@ -3171,6 +3172,15 @@ UINT AwtComponent::WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers) break; }; + // check dead key + if (isDeadKey) { + for (int i = 0; charToDeadVKTable[i].c != 0; i++) { + if (charToDeadVKTable[i].c == character) { + return charToDeadVKTable[i].javaKey; + } + } + } + // for the general case, use a bi-directional table for (int i = 0; keyMapTable[i].windowsKey != 0; i++) { if (keyMapTable[i].windowsKey == windowsKey) { @@ -3384,14 +3394,18 @@ AwtComponent::UpdateDynPrimaryKeymap(UINT wkey, UINT jkeyLegacy, jint keyLocatio } } -UINT AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops) +UINT AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops, BOOL &isDeadKey) { static Hashtable transTable("VKEY translations"); + static Hashtable deadKeyFlagTable("Dead Key Flags"); + isDeadKey = FALSE; // Try to translate using last saved translation if (ops == LOAD) { + void* deadKeyFlag = deadKeyFlagTable.remove(reinterpret_cast(static_cast(wkey))); void* value = transTable.remove(reinterpret_cast(static_cast(wkey))); if (value != NULL) { + isDeadKey = static_cast(reinterpret_cast(deadKeyFlag)); return static_cast(reinterpret_cast(value)); } } @@ -3484,12 +3498,13 @@ UINT AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops) // instead of creating our own conversion tables, I'll let Win32 // convert the character for me. - WORD mbChar; + WORD wChar[2]; UINT scancode = ::MapVirtualKey(wkey, 0); - int converted = ::ToAsciiEx(wkey, scancode, keyboardState, - &mbChar, 0, GetKeyboardLayout()); + int converted = ::ToUnicodeEx(wkey, scancode, keyboardState, + wChar, 2, 0, GetKeyboardLayout()); UINT translation; + BOOL deadKeyFlag = (converted == 2); // Dead Key if (converted < 0) { @@ -3508,16 +3523,16 @@ UINT AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops) } else // the caller expects a Unicode character. if (converted > 0) { - WCHAR unicodeChar[2]; - VERIFY(::MultiByteToWideChar(GetCodePage(), MB_PRECOMPOSED, - (LPCSTR)&mbChar, 1, unicodeChar, 1)); - - translation = unicodeChar[0]; + translation = wChar[0]; } if (ops == SAVE) { transTable.put(reinterpret_cast(static_cast(wkey)), reinterpret_cast(static_cast(translation))); + deadKeyFlagTable.put(reinterpret_cast(static_cast(wkey)), + reinterpret_cast(static_cast(deadKeyFlag))); } + + isDeadKey = deadKeyFlag; return translation; } @@ -3537,8 +3552,9 @@ MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt, UINT modifiers = GetJavaModifiers(); jint keyLocation = GetKeyLocation(wkey, flags); - UINT jkey = WindowsKeyToJavaKey(wkey, modifiers); - UINT character = WindowsKeyToJavaChar(wkey, modifiers, SAVE); + BOOL isDeadKey = FALSE; + UINT character = WindowsKeyToJavaChar(wkey, modifiers, SAVE, isDeadKey); + UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey); UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers); @@ -3579,8 +3595,9 @@ MsgRouting AwtComponent::WmKeyUp(UINT wkey, UINT repCnt, UINT modifiers = GetJavaModifiers(); jint keyLocation = GetKeyLocation(wkey, flags); - UINT jkey = WindowsKeyToJavaKey(wkey, modifiers); - UINT character = WindowsKeyToJavaChar(wkey, modifiers, LOAD); + BOOL isDeadKey = FALSE; + UINT character = WindowsKeyToJavaChar(wkey, modifiers, LOAD, isDeadKey); + UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey); UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers); SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED, @@ -5628,7 +5645,8 @@ void AwtComponent::_NativeHandleEvent(void *param) } } - modifiedChar = p->WindowsKeyToJavaChar(winKey, modifiers, AwtComponent::NONE); + BOOL isDeadKey = FALSE; + modifiedChar = p->WindowsKeyToJavaChar(winKey, modifiers, AwtComponent::NONE, isDeadKey); bCharChanged = (keyChar != modifiedChar); } break; @@ -7166,4 +7184,4 @@ void ReleaseDCList(HWND hwnd, DCList &list) { removedDCs = removedDCs->next; delete tmpDCList; } -} +} \ No newline at end of file diff --git a/jdk/src/windows/native/sun/windows/awt_Component.h b/jdk/src/windows/native/sun/windows/awt_Component.h index 75c1b3c9384..8ce8fa39112 100644 --- a/jdk/src/windows/native/sun/windows/awt_Component.h +++ b/jdk/src/windows/native/sun/windows/awt_Component.h @@ -441,7 +441,7 @@ public: static jint GetJavaModifiers(); static jint GetButton(int mouseButton); static UINT GetButtonMK(int mouseButton); - static UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers); + static UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers, UINT character, BOOL isDeadKey); static void JavaKeyToWindowsKey(UINT javaKey, UINT *windowsKey, UINT *modifiers, UINT originalWindowsKey); static void UpdateDynPrimaryKeymap(UINT wkey, UINT jkeyLegacy, jint keyLocation, UINT modifiers); @@ -453,7 +453,7 @@ public: enum TransOps {NONE, LOAD, SAVE}; - UINT WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops); + UINT WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops, BOOL &isDeadKey); /* routines used for input method support */ void SetInputMethod(jobject im, BOOL useNativeCompWindow); diff --git a/jdk/test/java/awt/Choice/ItemStateChangeTest/ItemStateChangeTest.java b/jdk/test/java/awt/Choice/ItemStateChangeTest/ItemStateChangeTest.java new file mode 100644 index 00000000000..45ccef0262b --- /dev/null +++ b/jdk/test/java/awt/Choice/ItemStateChangeTest/ItemStateChangeTest.java @@ -0,0 +1,128 @@ +/* + * 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 7171412 + @summary awt Choice doesn't fire ItemStateChange when selecting item after select() call + @author Oleg Pekhovskiy: area=awt-choice + @library ../../regtesthelpers + @build Util + @run main ItemStateChangeTest +*/ + +import test.java.awt.regtesthelpers.Util; + +import java.awt.*; +import java.awt.event.*; +import sun.awt.OSInfo; + +public class ItemStateChangeTest extends Frame { + + int events = 0; + + public static void main(String args[]) { + new ItemStateChangeTest(); + } + + public ItemStateChangeTest() { + + if (OSInfo.getOSType() != OSInfo.OSType.WINDOWS) { + return; + } + + try { + + final Robot robot = new Robot(); + robot.setAutoDelay(20); + Util.waitForIdle(robot); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + final Choice choice = new Choice(); + choice.add("A"); + choice.add("B"); + choice.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + ++events; + } + }); + + add(choice); + setSize(200, 150); + setVisible(true); + toFront(); + + // choose B + int y = chooseB(choice, robot, 16); + + // reset to A + choice.select(0); + robot.delay(20); + Util.waitForIdle(robot); + + // choose B again + chooseB(choice, robot, y); + + if (events == 2) { + System.out.println("Test passed!"); + } + else { + throw new RuntimeException("Test failed!"); + } + + } + catch (AWTException e) { + throw new RuntimeException("Test failed!"); + } + } + + final int chooseB(Choice choice, Robot robot, int y) { + while (true) { + // show drop-down list + Util.clickOnComp(choice, robot); + Util.waitForIdle(robot); + Point pt = choice.getLocationOnScreen(); + Dimension size = choice.getSize(); + // try to click B item + robot.mouseMove(pt.x + size.width / 2, pt.y + size.height + y); + Util.waitForIdle(robot); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + Util.waitForIdle(robot); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + Util.waitForIdle(robot); + if (choice.getSelectedIndex() == 1) { + break; + } + // if it's not B, position cursor lower by 2 pixels and try again + y += 2; + } + return y; + } +} diff --git a/jdk/test/java/awt/List/EmptyListEventTest/EmptyListEventTest.java b/jdk/test/java/awt/List/EmptyListEventTest/EmptyListEventTest.java new file mode 100644 index 00000000000..c5515afa6b2 --- /dev/null +++ b/jdk/test/java/awt/List/EmptyListEventTest/EmptyListEventTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2008, 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 6366126 + * @summary List throws ArrayIndexOutOfBoundsException when pressing ENTER after removing all the items, Win32 + * @author Dmitry Cherepanov area=awt.list + * @run main EmptyListEventTest + */ +import java.awt.*; +import java.awt.event.*; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import sun.awt.SunToolkit; + +public class EmptyListEventTest { + + private static List list; + + public static void main(String[] args) throws Exception { + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + createAndShowGUI(); + } + }); + + toolkit.realSync(); + + // press mouse -> ItemEvent + Point point = getClickPoint(); + robot.mouseMove(point.x, point.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + list.requestFocusInWindow(); + } + }); + + toolkit.realSync(); + + if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != list) { + throw new RuntimeException("Test failed - list isn't focus owner."); + } + + // press key ENTER -> ActionEvent + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + toolkit.realSync(); + + // press key SPACE -> ItemEvent + robot.keyPress(KeyEvent.VK_SPACE); + robot.keyRelease(KeyEvent.VK_SPACE); + toolkit.realSync(); + + // mouse double click -> ActionEvent + robot.setAutoDelay(10); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + toolkit.realSync(); + } + + private static Point getClickPoint() throws Exception { + final Point[] result = new Point[1]; + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + Point point = list.getLocationOnScreen(); + point.translate(list.getWidth() / 2, list.getHeight() / 2); + result[0] = point; + + } + }); + + return result[0]; + + + } + + private static void createAndShowGUI() { + JFrame frame = new JFrame(); + frame.setSize(200, 200); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JPanel panel = new JPanel(new BorderLayout()); + + frame.getToolkit().addAWTEventListener(new AWTEventListener() { + + public void eventDispatched(AWTEvent e) { + System.out.println(e); + } + }, AWTEvent.FOCUS_EVENT_MASK | AWTEvent.WINDOW_FOCUS_EVENT_MASK); + + + MyListener listener = new MyListener(); + + list = new List(4, true); + list.addActionListener(listener); + list.addItemListener(listener); + + panel.add(list); + + frame.getContentPane().add(panel); + frame.setVisible(true); + + } + + static class MyListener implements ActionListener, ItemListener { + + public void actionPerformed(ActionEvent ae) { + System.err.println(ae); + throw new RuntimeException("Test failed - list is empty so event is redundant"); + } + + public void itemStateChanged(ItemEvent ie) { + System.err.println(ie); + throw new RuntimeException("Test failed - list is empty so event is redundant"); + } + } +} diff --git a/jdk/test/java/awt/ScrollPane/ScrollPanePreferredSize/ScrollPanePreferredSize.java b/jdk/test/java/awt/ScrollPane/ScrollPanePreferredSize/ScrollPanePreferredSize.java new file mode 100644 index 00000000000..a8c3c822bc5 --- /dev/null +++ b/jdk/test/java/awt/ScrollPane/ScrollPanePreferredSize/ScrollPanePreferredSize.java @@ -0,0 +1,65 @@ +/* + * 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. 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. + */ + +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.ScrollPane; +import java.awt.Toolkit; + +import sun.awt.SunToolkit; + +/** + * @test + * @bug 7124213 + * @author Sergey Bylokhov + */ +public final class ScrollPanePreferredSize { + + public static void main(final String[] args) { + final Dimension expected = new Dimension(300, 300); + final Frame frame = new Frame(); + final ScrollPane sp = new ScrollPane(); + sp.setSize(expected); + frame.add(sp); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + sleep(); + final Dimension size = frame.getSize(); + if (size.width < expected.width || size.height < expected.height) { + throw new RuntimeException( + "Expected size: >= " + expected + ", actual size: " + size); + } + frame.dispose(); + } + + private static void sleep() { + ((SunToolkit) Toolkit.getDefaultToolkit()).realSync(); + try { + Thread.sleep(500L); + } catch (InterruptedException ignored) { + } + } +} diff --git a/jdk/test/java/awt/TextArea/TextAreaTwicePack/TextAreaTwicePack.java b/jdk/test/java/awt/TextArea/TextAreaTwicePack/TextAreaTwicePack.java new file mode 100644 index 00000000000..edd4eded97f --- /dev/null +++ b/jdk/test/java/awt/TextArea/TextAreaTwicePack/TextAreaTwicePack.java @@ -0,0 +1,66 @@ +/* + * 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. 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. + */ + +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.TextArea; +import java.awt.Toolkit; + +import sun.awt.SunToolkit; + +/** + * @test + * @bug 7160627 + * @summary We shouldn't get different frame size when we call Frame.pack() + * twice. + * @author Sergey Bylokhov + */ +public final class TextAreaTwicePack { + + public static void main(final String[] args) { + final Frame frame = new Frame(); + final TextArea ta = new TextArea(); + frame.add(ta); + frame.pack(); + frame.setVisible(true); + sleep(); + final Dimension before = frame.getSize(); + frame.pack(); + final Dimension after = frame.getSize(); + if (!after.equals(before)) { + throw new RuntimeException( + "Expected size: " + before + ", actual size: " + after); + } + frame.dispose(); + } + + private static void sleep() { + ((SunToolkit) Toolkit.getDefaultToolkit()).realSync(); + try { + Thread.sleep(500L); + } catch (InterruptedException ignored) { + } + } +} diff --git a/jdk/test/java/awt/event/KeyEvent/DeadKey/DeadKeyMacOSXInputText.java b/jdk/test/java/awt/event/KeyEvent/DeadKey/DeadKeyMacOSXInputText.java new file mode 100644 index 00000000000..3ae73c6e684 --- /dev/null +++ b/jdk/test/java/awt/event/KeyEvent/DeadKey/DeadKeyMacOSXInputText.java @@ -0,0 +1,131 @@ +/* + * 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 7199180 + * @summary [macosx] Dead keys handling for input methods + * @author alexandr.scherbatiy area=awt.event + * @run main DeadKeyMacOSXInputText + */ +import java.awt.*; +import java.awt.event.*; +import java.awt.event.KeyEvent; +import javax.swing.JTextField; +import sun.awt.OSInfo; +import sun.awt.SunToolkit; + +public class DeadKeyMacOSXInputText { + + private static SunToolkit toolkit; + private static volatile int state = 0; + + public static void main(String[] args) throws Exception { + + if (OSInfo.getOSType() != OSInfo.OSType.MACOSX) { + return; + } + + toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + createAndShowGUI(); + + // Pressed keys: Alt + E + A + // Results: ALT + VK_DEAD_ACUTE + a with accute accent + robot.keyPress(KeyEvent.VK_ALT); + robot.keyPress(KeyEvent.VK_E); + robot.keyRelease(KeyEvent.VK_E); + robot.keyRelease(KeyEvent.VK_ALT); + + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + toolkit.realSync(); + + if (state != 3) { + throw new RuntimeException("Wrong number of key events."); + } + } + + static void createAndShowGUI() { + Frame frame = new Frame(); + frame.setSize(300, 300); + Panel panel = new Panel(new BorderLayout()); + JTextField textField = new JTextField(); + textField.addKeyListener(new DeadKeyListener()); + panel.add(textField, BorderLayout.CENTER); + frame.add(panel); + frame.setVisible(true); + toolkit.realSync(); + + textField.requestFocusInWindow(); + toolkit.realSync(); + + } + + static class DeadKeyListener extends KeyAdapter { + + @Override + public void keyPressed(KeyEvent e) { + int keyCode = e.getKeyCode(); + char keyChar = e.getKeyChar(); + + switch (state) { + case 0: + if (keyCode != KeyEvent.VK_ALT) { + throw new RuntimeException("Alt is not pressed."); + } + state++; + break; + case 1: + if (keyCode != KeyEvent.VK_DEAD_ACUTE) { + throw new RuntimeException("Dead ACUTE is not pressed."); + } + if (keyChar != 0xB4) { + throw new RuntimeException("Pressed char is not dead acute."); + } + state++; + break; + } + } + + @Override + public void keyTyped(KeyEvent e) { + int keyCode = e.getKeyCode(); + char keyChar = e.getKeyChar(); + + if (state == 2) { + if (keyCode != 0) { + throw new RuntimeException("Key code should be undefined."); + } + if (keyChar != 0xE1) { + throw new RuntimeException("A char does not have ACCUTE accent"); + } + state++; + } else { + throw new RuntimeException("Wron number of keyTyped events."); + } + } + } +} diff --git a/jdk/test/javax/swing/JColorChooser/Test7194184.java b/jdk/test/javax/swing/JColorChooser/Test7194184.java new file mode 100644 index 00000000000..97599b12696 --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test7194184.java @@ -0,0 +1,113 @@ +/* + * 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. + */ + +/* + * Portions Copyright (c) 2012 IBM Corporation + */ + +/* + * @test + * @bug 7194184 + * @summary Tests JColorChooser Swatch keyboard accessibility. + * @author Sean Chou + * @library ../regtesthelpers + * @build Util + * @run main Test7194184 + */ + +import java.awt.Component; +import java.awt.AWTException; +import java.awt.Color; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.KeyEvent; + +import javax.swing.JColorChooser; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +import java.util.concurrent.Callable; +import sun.awt.SunToolkit; + +public class Test7194184 implements Runnable { + private static JFrame frame; + private static JColorChooser colorChooser; + private static Color selectedColor; + + public static void main(String[] args) throws Exception { + testKeyBoardAccess(); + } + + private static void testKeyBoardAccess() throws Exception { + Robot robot = new Robot(); + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + + SwingUtilities.invokeLater(new Test7194184()); + toolkit.realSync(); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + selectedColor = colorChooser.getColor(); + + Component recentSwatchPanel = Util.findSubComponent(colorChooser, "RecentSwatchPanel"); + if (recentSwatchPanel == null) { + throw new RuntimeException("RecentSwatchPanel not found"); + } + recentSwatchPanel.requestFocusInWindow(); + } + }); + + toolkit.realSync(); + + // Tab to move the focus to MainSwatch + Util.hitKeys(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_TAB); + + // Select the color on right + Util.hitKeys(robot, KeyEvent.VK_RIGHT); + Util.hitKeys(robot, KeyEvent.VK_RIGHT); + Util.hitKeys(robot, KeyEvent.VK_SPACE); + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame.dispose(); + if (selectedColor == colorChooser.getColor()) { + throw new RuntimeException("JColorChooser misses keyboard accessibility"); + } + } + }); + } + + public void run() { + String title = getClass().getName(); + frame = new JFrame(title); + colorChooser = new JColorChooser(); + + frame.add(colorChooser); + frame.pack(); + frame.setVisible(true); + } + +} diff --git a/jdk/test/javax/swing/ToolTipManager/7123767/bug7123767.java b/jdk/test/javax/swing/ToolTipManager/7123767/bug7123767.java new file mode 100644 index 00000000000..4c7402d3900 --- /dev/null +++ b/jdk/test/javax/swing/ToolTipManager/7123767/bug7123767.java @@ -0,0 +1,220 @@ +/* + * 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 7123767 + @summary Wrong tooltip location in Multi-Monitor configurations + @author Vladislav Karnaukhov + @run main bug7123767 +*/ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import javax.swing.plaf.metal.MetalLookAndFeel; +import java.awt.*; +import java.awt.event.MouseEvent; +import java.lang.reflect.InvocationTargetException; + +public class bug7123767 extends JFrame { + + private static class TestFactory extends PopupFactory { + + private static TestFactory newFactory = new TestFactory(); + private static PopupFactory oldFactory; + + private TestFactory() { + super(); + } + + public static void install() { + if (oldFactory == null) { + oldFactory = getSharedInstance(); + setSharedInstance(newFactory); + } + } + + public static void uninstall() { + if (oldFactory != null) { + setSharedInstance(oldFactory); + } + } + + // Actual test happens here + public Popup getPopup(Component owner, Component contents, int x, int y) { + GraphicsConfiguration mouseGC = testGC(MouseInfo.getPointerInfo().getLocation()); + if (mouseGC == null) { + throw new RuntimeException("Can't find GraphicsConfiguration that mouse pointer belongs to"); + } + + GraphicsConfiguration tipGC = testGC(new Point(x, y)); + if (tipGC == null) { + throw new RuntimeException("Can't find GraphicsConfiguration that tip belongs to"); + } + + if (!mouseGC.equals(tipGC)) { + throw new RuntimeException("Mouse and tip GCs are not equal"); + } + + return super.getPopup(owner, contents, x, y); + } + + private static GraphicsConfiguration testGC(Point pt) { + GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] devices = environment.getScreenDevices(); + for (GraphicsDevice device : devices) { + GraphicsConfiguration[] configs = device.getConfigurations(); + for (GraphicsConfiguration config : configs) { + Rectangle rect = config.getBounds(); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(config); + adjustInsets(rect, insets); + if (rect.contains(pt)) + return config; + } + } + + return null; + } + } + + private static final int MARGIN = 10; + private static bug7123767 frame; + private static Robot robot; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(new MetalLookAndFeel()); + setUp(); + testToolTip(); + TestFactory.uninstall(); + } + + // Creates a window that is stretched across all available monitors + // and adds itself as ContainerListener to track tooltips drawing + private bug7123767() { + super(); + + ToolTipManager.sharedInstance().setInitialDelay(0); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + TestFactory.install(); + + JLabel label1 = new JLabel("no preferred location"); + label1.setToolTipText("tip"); + add(label1, BorderLayout.WEST); + + JLabel label2 = new JLabel("preferred location (20000, 20000)") { + public Point getToolTipLocation(MouseEvent event) { + return new Point(20000, 20000); + } + }; + + label2.setToolTipText("tip"); + add(label2, BorderLayout.EAST); + + setUndecorated(true); + pack(); + + Rectangle rect = new Rectangle(); + GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] devices = environment.getScreenDevices(); + for (GraphicsDevice device : devices) { + GraphicsConfiguration[] configs = device.getConfigurations(); + for (GraphicsConfiguration config : configs) { + Insets localInsets = Toolkit.getDefaultToolkit().getScreenInsets(config); + Rectangle localRect = config.getBounds(); + adjustInsets(localRect, localInsets); + rect.add(localRect); + } + } + setBounds(rect); + } + + private static void setUp() throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame = new bug7123767(); + frame.setVisible(true); + } + }); + } + + // Moves mouse pointer to the corners of every GraphicsConfiguration + private static void testToolTip() throws AWTException { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + toolkit.realSync(); + + GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] devices = environment.getScreenDevices(); + for (GraphicsDevice device : devices) { + GraphicsConfiguration[] configs = device.getConfigurations(); + for (GraphicsConfiguration config : configs) { + Rectangle rect = config.getBounds(); + Insets insets = toolkit.getScreenInsets(config); + adjustInsets(rect, insets); + + // Upper left + glide(rect.x + rect.width / 2, rect.y + rect.height / 2, + rect.x + MARGIN, rect.y + MARGIN); + toolkit.realSync(); + + // Lower left + glide(rect.x + rect.width / 2, rect.y + rect.height / 2, + rect.x + MARGIN, rect.y + rect.height - MARGIN); + toolkit.realSync(); + + // Upper right + glide(rect.x + rect.width / 2, rect.y + rect.height / 2, + rect.x + rect.width - MARGIN, rect.y + MARGIN); + toolkit.realSync(); + + // Lower right + glide(rect.x + rect.width / 2, rect.y + rect.height / 2, + rect.x + rect.width - MARGIN, rect.y + rect.height - MARGIN); + toolkit.realSync(); + } + } + } + + private static void glide(int x0, int y0, int x1, int y1) throws AWTException { + if (robot == null) { + robot = new Robot(); + robot.setAutoDelay(20); + } + + float dmax = (float) Math.max(Math.abs(x1 - x0), Math.abs(y1 - y0)); + float dx = (x1 - x0) / dmax; + float dy = (y1 - y0) / dmax; + + robot.mouseMove(x0, y0); + for (int i = 1; i <= dmax; i += 10) { + robot.mouseMove((int) (x0 + dx * i), (int) (y0 + dy * i)); + } + } + + private static void adjustInsets(Rectangle rect, final Insets insets) { + rect.x += insets.left; + rect.y += insets.top; + rect.width -= (insets.left + insets.right); + rect.height -= (insets.top + insets.bottom); + } +}