--- a/jdk/make/mapfiles/libawt/mapfile-vers-linux Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/make/mapfiles/libawt/mapfile-vers-linux Tue Nov 17 13:09:16 2015 -0800
@@ -206,6 +206,7 @@
Java_sun_awt_X11GraphicsDevice_enumDisplayModes;
Java_sun_awt_X11GraphicsDevice_configDisplayMode;
Java_sun_awt_X11GraphicsDevice_resetNativeData;
+ Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor;
Java_sun_awt_X11GraphicsEnvironment_checkShmExt;
Java_sun_awt_X11GraphicsEnvironment_getDefaultScreenNum;
Java_sun_awt_X11GraphicsEnvironment_getDisplayString;
--- a/jdk/make/mapfiles/libawt_xawt/mapfile-vers Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/make/mapfiles/libawt_xawt/mapfile-vers Tue Nov 17 13:09:16 2015 -0800
@@ -214,6 +214,7 @@
Java_sun_awt_X11GraphicsDevice_enumDisplayModes;
Java_sun_awt_X11GraphicsDevice_configDisplayMode;
Java_sun_awt_X11GraphicsDevice_resetNativeData;
+ Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor;
Java_sun_awt_X11GraphicsConfig_initIDs;
Java_sun_awt_X11GraphicsConfig_getXResolution;
Java_sun_awt_X11GraphicsConfig_getYResolution;
--- a/jdk/src/java.base/windows/native/launcher/java.manifest Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.base/windows/native/launcher/java.manifest Tue Nov 17 13:09:16 2015 -0800
@@ -37,7 +37,7 @@
<!-- Indicate JDK is high-dpi aware. -->
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
- <dpiAware>true</dpiAware>
+ <dpiAware>true/PM</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/macosx/classes/sun/font/CCompositeGlyphMapper.java Tue Nov 17 13:09:16 2015 -0800
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2015, 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.font;
+
+public final class CCompositeGlyphMapper extends CompositeGlyphMapper {
+
+ private CompositeFont font;
+ private CharToGlyphMapper slotMappers[];
+
+ public CCompositeGlyphMapper(CompositeFont compFont) {
+ super(compFont);
+ font = compFont;
+ slotMappers = new CharToGlyphMapper[font.numSlots];
+ missingGlyph = 0;
+ }
+
+ private CharToGlyphMapper getSlotMapper(int slot) {
+ CharToGlyphMapper mapper = slotMappers[slot];
+ if (mapper == null) {
+ mapper = font.getSlotFont(slot).getMapper();
+ slotMappers[slot] = mapper;
+ }
+ return mapper;
+ }
+
+ public boolean canDisplay(char ch) {
+ int glyph = charToGlyph(ch);
+ return glyph != missingGlyph;
+ }
+
+ private int convertToGlyph(int unicode) {
+ for (int slot = 0; slot < font.numSlots; slot++) {
+ CharToGlyphMapper mapper = getSlotMapper(slot);
+ int glyphCode = mapper.charToGlyph(unicode);
+ // The CFont Mappers will return a negative code
+ // for fonts that will fill the glyph from fallbacks
+ // - cascading font in OSX-speak. But we need to be
+ // know here that only the codes > 0 are really present.
+ if (glyphCode > 0) {
+ glyphCode = compositeGlyphCode(slot, glyphCode);
+ return glyphCode;
+ }
+ }
+ return missingGlyph;
+ }
+
+ public int getNumGlyphs() {
+ int numGlyphs = 0;
+ for (int slot=0; slot<1 /*font.numSlots*/; slot++) {
+ CharToGlyphMapper mapper = slotMappers[slot];
+ if (mapper == null) {
+ mapper = font.getSlotFont(slot).getMapper();
+ slotMappers[slot] = mapper;
+ }
+ numGlyphs += mapper.getNumGlyphs();
+ }
+ return numGlyphs;
+ }
+
+ public int charToGlyph(int unicode) {
+ return convertToGlyph(unicode);
+ }
+
+ public int charToGlyph(char unicode) {
+ return convertToGlyph(unicode);
+ }
+
+ public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) {
+
+ for (int i=0; i<count; i++) {
+ int code = unicodes[i]; // char is unsigned.
+
+ if (code >= HI_SURROGATE_START &&
+ code <= HI_SURROGATE_END && i < count - 1) {
+ char low = unicodes[i + 1];
+
+ if (low >= LO_SURROGATE_START &&
+ low <= LO_SURROGATE_END) {
+ code = (code - HI_SURROGATE_START) *
+ 0x400 + low - LO_SURROGATE_START + 0x10000;
+ glyphs[i + 1] = INVISIBLE_GLYPH_ID;
+ }
+ }
+
+ glyphs[i] = convertToGlyph(code);
+
+ if (code < FontUtilities.MIN_LAYOUT_CHARCODE) {
+ continue;
+ }
+ else if (FontUtilities.isComplexCharCode(code)) {
+ return true;
+ }
+ else if (code >= 0x10000) {
+ i += 1; // Empty glyph slot after surrogate
+ continue;
+ }
+ }
+
+ return false;
+ }
+
+ public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) {
+ for (int i=0; i<count; i++) {
+ int code = unicodes[i]; // char is unsigned.
+
+ if (code >= HI_SURROGATE_START &&
+ code <= HI_SURROGATE_END && i < count - 1) {
+ char low = unicodes[i + 1];
+
+ if (low >= LO_SURROGATE_START &&
+ low <= LO_SURROGATE_END) {
+ code = (code - HI_SURROGATE_START) *
+ 0x400 + low - LO_SURROGATE_START + 0x10000;
+
+ glyphs[i] = convertToGlyph(code);
+ i += 1; // Empty glyph slot after surrogate
+ glyphs[i] = INVISIBLE_GLYPH_ID;
+ continue;
+ }
+ }
+
+ glyphs[i] = convertToGlyph(code);
+ }
+ }
+
+ public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) {
+ for (int i=0; i<count; i++) {
+ glyphs[i] = convertToGlyph(unicodes[i]);
+ }
+ }
+
+}
--- a/jdk/src/java.desktop/macosx/classes/sun/font/CFont.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/font/CFont.java Tue Nov 17 13:09:16 2015 -0800
@@ -31,12 +31,13 @@
import java.awt.geom.GeneralPath;;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
// Right now this class is final to avoid a problem with native code.
// For some reason the JNI IsInstanceOf was not working correctly
// so we are checking the class specifically. If we subclass this
// we need to modify the native code in CFontWrapper.m
-public final class CFont extends PhysicalFont {
+public final class CFont extends PhysicalFont implements FontSubstitution {
/* CFontStrike doesn't call these methods so they are unimplemented.
* They are here to meet the requirements of PhysicalFont, needed
@@ -76,6 +77,20 @@
throw new InternalError("Not implemented");
}
+ @Override
+ protected long getLayoutTableCache() {
+ return getLayoutTableCacheNative(getNativeFontPtr());
+ }
+
+ @Override
+ protected byte[] getTableBytes(int tag) {
+ return getTableBytesNative(getNativeFontPtr(), tag);
+ }
+
+ private native synchronized long getLayoutTableCacheNative(long nativeFontPtr);
+
+ private native byte[] getTableBytesNative(long nativeFontPtr, int tag);
+
private static native long createNativeFont(final String nativeFontName,
final int style);
private static native void disposeNativeFont(final long nativeFontPtr);
@@ -179,10 +194,51 @@
protected synchronized long getNativeFontPtr() {
if (nativeFontPtr == 0L) {
nativeFontPtr = createNativeFont(nativeFontName, style);
-}
+ }
return nativeFontPtr;
}
+ static native void getCascadeList(long nativeFontPtr, ArrayList<String> listOfString);
+
+ private CompositeFont createCompositeFont() {
+ ArrayList<String> listOfString = new ArrayList<String>();
+ getCascadeList(nativeFontPtr, listOfString);
+
+ FontManager fm = FontManagerFactory.getInstance();
+ int numFonts = 1 + listOfString.size();
+ PhysicalFont[] fonts = new PhysicalFont[numFonts];
+ fonts[0] = this;
+ int idx = 1;
+ for (String s : listOfString) {
+ if (s.equals(".AppleSymbolsFB")) {
+ // Don't know why we get the weird name above .. replace.
+ s = "AppleSymbols";
+ }
+ Font2D f2d = fm.findFont2D(s, Font.PLAIN, FontManager.NO_FALLBACK);
+ if (f2d == null || f2d == this) {
+ continue;
+ }
+ fonts[idx++] = (PhysicalFont)f2d;
+ }
+ if (idx < fonts.length) {
+ PhysicalFont[] orig = fonts;
+ fonts = new PhysicalFont[idx];
+ System.arraycopy(orig, 0, fonts, 0, idx);
+ }
+ CompositeFont compFont = new CompositeFont(fonts);
+ compFont.mapper = new CCompositeGlyphMapper(compFont);
+ return compFont;
+ }
+
+ private CompositeFont compFont;
+
+ public CompositeFont getCompositeFont2D() {
+ if (compFont == null) {
+ compFont = createCompositeFont();
+ }
+ return compFont;
+ }
+
protected synchronized void finalize() {
if (nativeFontPtr != 0) {
disposeNativeFont(nativeFontPtr);
--- a/jdk/src/java.desktop/macosx/classes/sun/font/CStrike.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/font/CStrike.java Tue Nov 17 13:09:16 2015 -0800
@@ -31,7 +31,7 @@
import sun.awt.SunHints;
-public final class CStrike extends FontStrike {
+public final class CStrike extends PhysicalStrike {
// Creates the native strike
private static native long createNativeStrikePtr(long nativeFontPtr,
--- a/jdk/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java Tue Nov 17 13:09:16 2015 -0800
@@ -166,7 +166,12 @@
}
@Override
- public int getDefaultScale() {
+ public double getDefaultScaleX() {
+ return scale;
+ }
+
+ @Override
+ public double getDefaultScaleY() {
return scale;
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java Tue Nov 17 13:09:16 2015 -0800
@@ -1156,7 +1156,9 @@
&& !(dst instanceof NullSurfaceData)
&& !(src instanceof NullSurfaceData)
&& src.getSurfaceType().equals(dst.getSurfaceType())
- && src.getDefaultScale() == dst.getDefaultScale()) {
+ && src.getDefaultScaleX() == dst.getDefaultScaleX()
+ && src.getDefaultScaleY() == dst.getDefaultScaleY())
+ {
final Rectangle size = src.getBounds();
final Blit blit = Blit.locate(src.getSurfaceType(),
CompositeType.Src,
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.h Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.h Tue Nov 17 13:09:16 2015 -0800
@@ -26,6 +26,8 @@
#import <Cocoa/Cocoa.h>
#import <JavaRuntimeSupport/JavaRuntimeSupport.h>
+#import "fontscalerdefs.h"
+
#define MAX_STACK_ALLOC_GLYPH_BUFFER_SIZE 256
@interface AWTFont : NSObject {
@@ -33,6 +35,7 @@
NSFont *fFont;
CGFontRef fNativeCGFont;
BOOL fIsFakeItalic;
+ TTLayoutTableCache* layoutTableCache;
}
+ (AWTFont *) awtFontForName:(NSString *)name
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m Tue Nov 17 13:09:16 2015 -0800
@@ -42,10 +42,33 @@
if (self) {
fFont = [font retain];
fNativeCGFont = CTFontCopyGraphicsFont((CTFontRef)font, NULL);
+ layoutTableCache = NULL;
}
return self;
}
+static TTLayoutTableCache* newCFontLayoutTableCache() {
+ TTLayoutTableCache* ltc = calloc(1, sizeof(TTLayoutTableCache));
+ if (ltc) {
+ int i;
+ for(i=0;i<LAYOUTCACHE_ENTRIES;i++) {
+ ltc->entries[i].len = -1;
+ }
+ }
+ return ltc;
+}
+
+static void freeCFontLayoutTableCache(TTLayoutTableCache* ltc) {
+ if (ltc) {
+ int i;
+ for(i=0;i<LAYOUTCACHE_ENTRIES;i++) {
+ if(ltc->entries[i].ptr) free (ltc->entries[i].ptr);
+ }
+ if (ltc->kernPairs) free(ltc->kernPairs);
+ free(ltc);
+ }
+}
+
- (void) dealloc {
[fFont release];
fFont = nil;
@@ -53,6 +76,10 @@
if (fNativeCGFont) {
CGFontRelease(fNativeCGFont);
fNativeCGFont = NULL;
+ if (layoutTableCache != NULL) {
+ freeCFontLayoutTableCache(layoutTableCache);
+ layoutTableCache = NULL;
+ }
}
[super dealloc];
@@ -63,6 +90,10 @@
CGFontRelease(fNativeCGFont);
fNativeCGFont = NULL;
}
+ if (layoutTableCache != NULL) {
+ freeCFontLayoutTableCache(layoutTableCache);
+ layoutTableCache = NULL;
+ }
[super finalize];
}
@@ -345,6 +376,95 @@
/*
* Class: sun_font_CFont
+ * Method: getPlatformFontPtrNative
+ * Signature: (JI)[B
+ */
+JNIEXPORT jlong JNICALL
+Java_sun_font_CFont_getCGFontPtrNative
+ (JNIEnv *env, jclass clazz,
+ jlong awtFontPtr)
+{
+ AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
+ return (jlong)(awtFont->fNativeCGFont);
+}
+
+/*
+ * Class: sun_font_CFont
+ * Method: getLayoutTableCacheNative
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL
+Java_sun_font_CFont_getLayoutTableCacheNative
+ (JNIEnv *env, jclass clazz,
+ jlong awtFontPtr)
+{
+ AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
+ if (awtFont->layoutTableCache == NULL) {
+ awtFont->layoutTableCache = newCFontLayoutTableCache();
+ }
+ return (jlong)(awtFont->layoutTableCache);
+}
+
+/*
+ * Class: sun_font_CFont
+ * Method: getTableBytesNative
+ * Signature: (JI)[B
+ */
+JNIEXPORT jbyteArray JNICALL
+Java_sun_font_CFont_getTableBytesNative
+ (JNIEnv *env, jclass clazz,
+ jlong awtFontPtr, jint jtag)
+{
+ jbyteArray jbytes = NULL;
+JNF_COCOA_ENTER(env);
+
+ CTFontTableTag tag = (CTFontTableTag)jtag;
+ int i, found = 0;
+ AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
+ NSFont* nsFont = awtFont->fFont;
+ CTFontRef ctfont = (CTFontRef)nsFont;
+ CFArrayRef tagsArray =
+ CTFontCopyAvailableTables(ctfont, kCTFontTableOptionNoOptions);
+ CFIndex numTags = CFArrayGetCount(tagsArray);
+ for (i=0; i<numTags; i++) {
+ if (tag ==
+ (CTFontTableTag)(uintptr_t)CFArrayGetValueAtIndex(tagsArray, i)) {
+ found = 1;
+ break;
+ }
+ }
+ CFRelease(tagsArray);
+ if (!found) {
+ return NULL;
+ }
+ CFDataRef table = CTFontCopyTable(ctfont, tag, kCTFontTableOptionNoOptions);
+ if (table == NULL) {
+ return NULL;
+ }
+
+ char *tableBytes = (char*)(CFDataGetBytePtr(table));
+ size_t tableLength = CFDataGetLength(table);
+ if (tableBytes == NULL || tableLength == 0) {
+ CFRelease(table);
+ return NULL;
+ }
+
+ jbytes = (*env)->NewByteArray(env, (jsize)tableLength);
+ if (jbytes == NULL) {
+ return NULL;
+ }
+ (*env)->SetByteArrayRegion(env, jbytes, 0,
+ (jsize)tableLength,
+ (jbyte*)tableBytes);
+ CFRelease(table);
+
+JNF_COCOA_EXIT(env);
+
+ return jbytes;
+}
+
+/*
+ * Class: sun_font_CFont
* Method: initNativeFont
* Signature: (Ljava/lang/String;I)J
*/
@@ -460,3 +580,42 @@
{
}
#endif
+
+/*
+ * Class: sun_awt_FontDescriptor
+ * Method: initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_sun_font_CFont_getCascadeList
+ (JNIEnv *env, jclass cls, jlong awtFontPtr, jobject arrayListOfString)
+{
+ jclass alc = (*env)->FindClass(env, "java/util/ArrayList");
+ if (alc == NULL) return;
+ jmethodID addMID = (*env)->GetMethodID(env, alc, "add", "(Ljava/lang/Object;)Z");
+ if (addMID == NULL) return;
+
+ CFIndex i;
+ AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
+ NSFont* nsFont = awtFont->fFont;
+ CTFontRef font = (CTFontRef)nsFont;
+ CFStringRef base = CTFontCopyFullName(font);
+ CFArrayRef codes = CFLocaleCopyISOLanguageCodes();
+
+#ifdef DEBUG
+ NSLog(@"BaseFont is : %@", (NSString*)base);
+#endif
+ CFArrayRef fds = CTFontCopyDefaultCascadeListForLanguages(font, codes);
+ CFIndex cnt = CFArrayGetCount(fds);
+ for (i=0; i<cnt; i++) {
+ CTFontDescriptorRef ref = CFArrayGetValueAtIndex(fds, i);
+ CFStringRef fontname =
+ CTFontDescriptorCopyAttribute(ref, kCTFontNameAttribute);
+#ifdef DEBUG
+ NSLog(@"Font is : %@", (NSString*)fontname);
+#endif
+ jstring jFontName = (jstring)JNFNSToJavaString(env, fontname);
+ (*env)->CallBooleanMethod(env, arrayListOfString, addMID, jFontName);
+ (*env)->DeleteLocalRef(env, jFontName);
+ }
+}
--- a/jdk/src/java.desktop/share/classes/javax/swing/JInternalFrame.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JInternalFrame.java Tue Nov 17 13:09:16 2015 -0800
@@ -1753,11 +1753,6 @@
if (isVisible()) {
setVisible(false);
}
- if (isSelected()) {
- try {
- setSelected(false);
- } catch (PropertyVetoException pve) {}
- }
if (!isClosed) {
firePropertyChange(IS_CLOSED_PROPERTY, Boolean.FALSE, Boolean.TRUE);
isClosed = true;
--- a/jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java Tue Nov 17 13:09:16 2015 -0800
@@ -2095,9 +2095,10 @@
*/
void setDisplayedMnemonicIndex(int mnemonicIndex) {
if (this.mnemonicIndex != mnemonicIndex) {
- if (mnemonicIndex != -1 && (title == null ||
+ String t = getTitle();
+ if (mnemonicIndex != -1 && (t == null ||
mnemonicIndex < 0 ||
- mnemonicIndex >= title.length())) {
+ mnemonicIndex >= t.length())) {
throw new IllegalArgumentException(
"Invalid mnemonic index: " + mnemonicIndex);
}
@@ -2116,7 +2117,7 @@
void updateDisplayedMnemonicIndex() {
setDisplayedMnemonicIndex(
- SwingUtilities.findDisplayedMnemonicIndex(title, mnemonic));
+ SwingUtilities.findDisplayedMnemonicIndex(getTitle(), mnemonic));
}
/////////////////
@@ -2133,10 +2134,9 @@
public String getAccessibleName() {
if (accessibleName != null) {
return accessibleName;
- } else if (title != null) {
- return title;
+ } else {
+ return getTitle();
}
- return null;
}
public String getAccessibleDescription() {
@@ -2156,7 +2156,7 @@
AccessibleStateSet states;
states = parent.getAccessibleContext().getAccessibleStateSet();
states.add(AccessibleState.SELECTABLE);
- int i = parent.indexOfTab(title);
+ int i = parent.indexOfTabComponent(tabComponent);
if (i == parent.getSelectedIndex()) {
states.add(AccessibleState.SELECTED);
}
@@ -2164,7 +2164,7 @@
}
public int getAccessibleIndexInParent() {
- return parent.indexOfTab(title);
+ return parent.indexOfTabComponent(tabComponent);
}
public int getAccessibleChildrenCount() {
@@ -2272,10 +2272,8 @@
}
public Rectangle getBounds() {
- int i = parent.indexOfTab(title);
- // Check for no title. Even though that's a bug in the app we should
- // inhibit an ArrayIndexOutOfBoundsException from getTabBounds.
- return (i == -1) ? null : parent.getUI().getTabBounds(parent, i);
+ return parent.getUI().
+ getTabBounds(parent, parent.indexOfTabComponent(tabComponent));
}
public void setBounds(Rectangle r) {
@@ -2343,6 +2341,11 @@
return null;
}
}
+
+ private String getTitle() {
+ return getTitleAt(parent.indexOfComponent(component));
+ }
+
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/TablePrintable.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/TablePrintable.java Tue Nov 17 13:09:16 2015 -0800
@@ -205,11 +205,9 @@
*/
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
throws PrinterException {
-
// for easy access to these values
final int imgWidth = (int)pageFormat.getImageableWidth();
final int imgHeight = (int)pageFormat.getImageableHeight();
-
if (imgWidth <= 0) {
throw new PrinterException("Width of printable area is too small.");
}
@@ -302,10 +300,12 @@
// been divided by it
int scaledWidth = (int)(imgWidth / sf);
int scaledHeight = (int)((availableSpace - hclip.height) / sf);
-
// calculate the area of the table to be printed for this page
findNextClip(scaledWidth, scaledHeight);
+ if (!((table.getBounds()).intersects(clip))) {
+ return NO_SUCH_PAGE;
+ }
last++;
}
@@ -343,7 +343,6 @@
tempRect.width = imgWidth;
tempRect.height = availableSpace;
g2d.clip(tempRect);
-
// if we have a scale factor, scale the graphics object to fit
// the entire width
if (sf != 1.0D) {
@@ -389,7 +388,26 @@
// draw a box around the table
g2d.setColor(Color.BLACK);
- g2d.drawRect(0, 0, clip.width, hclip.height + clip.height);
+
+ // compute the visible portion of table and draw the rect around it
+ Rectangle visibleBounds = clip.intersection(table.getBounds());
+ Point upperLeft = visibleBounds.getLocation();
+ Point lowerRight = new Point(visibleBounds.x + visibleBounds.width,
+ visibleBounds.y + visibleBounds.height);
+
+ int rMin = table.rowAtPoint(upperLeft);
+ int rMax = table.rowAtPoint(lowerRight);
+ if (rMin == -1) {
+ rMin = 0;
+ }
+ if (rMax == -1) {
+ rMax = table.getRowCount();
+ }
+ int rowHeight = 0;
+ for(int visrow = rMin; visrow < rMax; visrow++) {
+ rowHeight += table.getRowHeight(visrow);
+ }
+ g2d.drawRect(0, 0, visibleBounds.width, hclip.height + rowHeight);
// dispose the graphics copy
g2d.dispose();
@@ -509,7 +527,6 @@
if (++col >= colCount) {
// reset col to 0 to indicate we're finished all columns
col = 0;
-
break;
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java Tue Nov 17 13:09:16 2015 -0800
@@ -1812,9 +1812,11 @@
boolean ltr = table.getComponentOrientation().isLeftToRight();
- Point upperLeft = clip.getLocation();
- Point lowerRight = new Point(clip.x + clip.width - 1,
- clip.y + clip.height - 1);
+ // compute the visible part of table which needs to be painted
+ Rectangle visibleBounds = clip.intersection(bounds);
+ Point upperLeft = visibleBounds.getLocation();
+ Point lowerRight = new Point(visibleBounds.x + visibleBounds.width - 1,
+ visibleBounds.y + visibleBounds.height - 1);
int rMin = table.rowAtPoint(upperLeft);
int rMax = table.rowAtPoint(lowerRight);
@@ -1843,6 +1845,21 @@
cMax = table.getColumnCount()-1;
}
+ Container comp = SwingUtilities.getUnwrappedParent(table);
+ if (comp != null) {
+ comp = comp.getParent();
+ }
+
+ if (comp != null && !(comp instanceof JViewport) && !(comp instanceof JScrollPane)) {
+ // We did rMax-1 to paint the same number of rows that are drawn on console
+ // otherwise 1 extra row is printed per page than that are displayed
+ // when there is no scrollPane and we do printing of table
+ // but not when rmax is already pointing to index of last row
+ if (rMax != (table.getRowCount() - 1)) {
+ rMax = rMax - 1;
+ }
+ }
+
// Paint the grid.
paintGrid(g, rMin, rMax, cMin, cMax);
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/BufImgSurfaceData.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/BufImgSurfaceData.java Tue Nov 17 13:09:16 2015 -0800
@@ -50,6 +50,8 @@
BufferedImage bufImg;
private BufferedImageGraphicsConfig graphicsConfig;
RenderLoops solidloops;
+ private final double scaleX;
+ private final double scaleY;
private static native void initIDs(Class<?> ICM, Class<?> ICMColorData);
@@ -73,6 +75,12 @@
}
public static SurfaceData createData(BufferedImage bufImg) {
+ return createData(bufImg, 1, 1);
+ }
+
+ public static SurfaceData createData(BufferedImage bufImg,
+ double scaleX, double scaleY)
+ {
if (bufImg == null) {
throw new NullPointerException("BufferedImage cannot be null");
}
@@ -82,31 +90,36 @@
// REMIND: Check the image type and pick an appropriate subclass
switch (type) {
case BufferedImage.TYPE_INT_BGR:
- sData = createDataIC(bufImg, SurfaceType.IntBgr);
+ sData = createDataIC(bufImg, SurfaceType.IntBgr, scaleX, scaleY);
break;
case BufferedImage.TYPE_INT_RGB:
- sData = createDataIC(bufImg, SurfaceType.IntRgb);
+ sData = createDataIC(bufImg, SurfaceType.IntRgb, scaleX, scaleY);
break;
case BufferedImage.TYPE_INT_ARGB:
- sData = createDataIC(bufImg, SurfaceType.IntArgb);
+ sData = createDataIC(bufImg, SurfaceType.IntArgb, scaleX, scaleY);
break;
case BufferedImage.TYPE_INT_ARGB_PRE:
- sData = createDataIC(bufImg, SurfaceType.IntArgbPre);
+ sData = createDataIC(bufImg, SurfaceType.IntArgbPre, scaleX, scaleY);
break;
case BufferedImage.TYPE_3BYTE_BGR:
- sData = createDataBC(bufImg, SurfaceType.ThreeByteBgr, 2);
+ sData = createDataBC(bufImg, SurfaceType.ThreeByteBgr, 2,
+ scaleX, scaleY);
break;
case BufferedImage.TYPE_4BYTE_ABGR:
- sData = createDataBC(bufImg, SurfaceType.FourByteAbgr, 3);
+ sData = createDataBC(bufImg, SurfaceType.FourByteAbgr, 3,
+ scaleX, scaleY);
break;
case BufferedImage.TYPE_4BYTE_ABGR_PRE:
- sData = createDataBC(bufImg, SurfaceType.FourByteAbgrPre, 3);
+ sData = createDataBC(bufImg, SurfaceType.FourByteAbgrPre, 3,
+ scaleX, scaleY);
break;
case BufferedImage.TYPE_USHORT_565_RGB:
- sData = createDataSC(bufImg, SurfaceType.Ushort565Rgb, null);
+ sData = createDataSC(bufImg, SurfaceType.Ushort565Rgb, null,
+ scaleX, scaleY);
break;
case BufferedImage.TYPE_USHORT_555_RGB:
- sData = createDataSC(bufImg, SurfaceType.Ushort555Rgb, null);
+ sData = createDataSC(bufImg, SurfaceType.Ushort555Rgb, null,
+ scaleX, scaleY);
break;
case BufferedImage.TYPE_BYTE_INDEXED:
{
@@ -128,14 +141,16 @@
default:
throw new InternalError("Unrecognized transparency");
}
- sData = createDataBC(bufImg, sType, 0);
+ sData = createDataBC(bufImg, sType, 0, scaleX, scaleY);
}
break;
case BufferedImage.TYPE_BYTE_GRAY:
- sData = createDataBC(bufImg, SurfaceType.ByteGray, 0);
+ sData = createDataBC(bufImg, SurfaceType.ByteGray, 0,
+ scaleX, scaleY);
break;
case BufferedImage.TYPE_USHORT_GRAY:
- sData = createDataSC(bufImg, SurfaceType.UshortGray, null);
+ sData = createDataSC(bufImg, SurfaceType.UshortGray, null,
+ scaleX, scaleY);
break;
case BufferedImage.TYPE_BYTE_BINARY:
{
@@ -154,7 +169,7 @@
default:
throw new InternalError("Unrecognized pixel size");
}
- sData = createDataBP(bufImg, sType);
+ sData = createDataBP(bufImg, sType, scaleX, scaleY);
}
break;
case BufferedImage.TYPE_CUSTOM:
@@ -191,7 +206,7 @@
sType = SurfaceType.AnyDcm;
}
}
- sData = createDataIC(bufImg, sType);
+ sData = createDataIC(bufImg, sType, scaleX, scaleY);
break;
} else if (raster instanceof ShortComponentRaster &&
raster.getNumDataElements() == 1 &&
@@ -233,11 +248,12 @@
icm = null;
}
}
- sData = createDataSC(bufImg, sType, icm);
+ sData = createDataSC(bufImg, sType, icm, scaleX, scaleY);
break;
}
- sData = new BufImgSurfaceData(raster.getDataBuffer(),
- bufImg, SurfaceType.Custom);
+ sData = new BufImgSurfaceData(raster.getDataBuffer(), bufImg,
+ SurfaceType.Custom,
+ scaleX, scaleY);
}
break;
}
@@ -250,11 +266,15 @@
}
public static SurfaceData createDataIC(BufferedImage bImg,
- SurfaceType sType) {
+ SurfaceType sType,
+ double scaleX,
+ double scaleY)
+ {
IntegerComponentRaster icRaster =
(IntegerComponentRaster)bImg.getRaster();
BufImgSurfaceData bisd =
- new BufImgSurfaceData(icRaster.getDataBuffer(), bImg, sType);
+ new BufImgSurfaceData(icRaster.getDataBuffer(), bImg, sType,
+ scaleX, scaleY);
bisd.initRaster(icRaster.getDataStorage(),
icRaster.getDataOffset(0) * 4, 0,
icRaster.getWidth(),
@@ -267,11 +287,14 @@
public static SurfaceData createDataSC(BufferedImage bImg,
SurfaceType sType,
- IndexColorModel icm) {
+ IndexColorModel icm,
+ double scaleX, double scaleY)
+ {
ShortComponentRaster scRaster =
(ShortComponentRaster)bImg.getRaster();
BufImgSurfaceData bisd =
- new BufImgSurfaceData(scRaster.getDataBuffer(), bImg, sType);
+ new BufImgSurfaceData(scRaster.getDataBuffer(), bImg, sType,
+ scaleX, scaleY);
bisd.initRaster(scRaster.getDataStorage(),
scRaster.getDataOffset(0) * 2, 0,
scRaster.getWidth(),
@@ -284,11 +307,14 @@
public static SurfaceData createDataBC(BufferedImage bImg,
SurfaceType sType,
- int primaryBank) {
+ int primaryBank,
+ double scaleX, double scaleY)
+ {
ByteComponentRaster bcRaster =
(ByteComponentRaster)bImg.getRaster();
BufImgSurfaceData bisd =
- new BufImgSurfaceData(bcRaster.getDataBuffer(), bImg, sType);
+ new BufImgSurfaceData(bcRaster.getDataBuffer(), bImg, sType,
+ scaleX, scaleY);
ColorModel cm = bImg.getColorModel();
IndexColorModel icm = ((cm instanceof IndexColorModel)
? (IndexColorModel) cm
@@ -304,11 +330,14 @@
}
public static SurfaceData createDataBP(BufferedImage bImg,
- SurfaceType sType) {
+ SurfaceType sType,
+ double scaleX, double scaleY)
+ {
BytePackedRaster bpRaster =
(BytePackedRaster)bImg.getRaster();
BufImgSurfaceData bisd =
- new BufImgSurfaceData(bpRaster.getDataBuffer(), bImg, sType);
+ new BufImgSurfaceData(bpRaster.getDataBuffer(), bImg, sType,
+ scaleX, scaleY);
ColorModel cm = bImg.getColorModel();
IndexColorModel icm = ((cm instanceof IndexColorModel)
? (IndexColorModel) cm
@@ -350,15 +379,22 @@
IndexColorModel icm);
public BufImgSurfaceData(DataBuffer db,
- BufferedImage bufImg, SurfaceType sType)
+ BufferedImage bufImg,
+ SurfaceType sType,
+ double scaleX,
+ double scaleY)
{
super(SunWritableRaster.stealTrackable(db),
sType, bufImg.getColorModel());
this.bufImg = bufImg;
+ this.scaleX = scaleX;
+ this.scaleY = scaleY;
}
protected BufImgSurfaceData(SurfaceType surfaceType, ColorModel cm) {
super(surfaceType, cm);
+ this.scaleX = 1;
+ this.scaleY = 1;
}
public void initSolidLoops() {
@@ -395,7 +431,8 @@
public synchronized GraphicsConfiguration getDeviceConfiguration() {
if (graphicsConfig == null) {
- graphicsConfig = BufferedImageGraphicsConfig.getConfig(bufImg);
+ graphicsConfig = BufferedImageGraphicsConfig
+ .getConfig(bufImg, scaleX, scaleY);
}
return graphicsConfig;
}
@@ -418,6 +455,16 @@
return bufImg;
}
+ @Override
+ public double getDefaultScaleX() {
+ return scaleX;
+ }
+
+ @Override
+ public double getDefaultScaleY() {
+ return scaleY;
+ }
+
public static final class ICMColorData {
private long pData = 0L;
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/BufferedImageGraphicsConfig.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/BufferedImageGraphicsConfig.java Tue Nov 17 13:09:16 2015 -0800
@@ -45,19 +45,32 @@
extends GraphicsConfiguration
{
private static final int numconfigs = BufferedImage.TYPE_BYTE_BINARY;
- private static BufferedImageGraphicsConfig configs[] =
+ private static BufferedImageGraphicsConfig standardConfigs[] =
+ new BufferedImageGraphicsConfig[numconfigs];
+ private static BufferedImageGraphicsConfig scaledConfigs[] =
new BufferedImageGraphicsConfig[numconfigs];
public static BufferedImageGraphicsConfig getConfig(BufferedImage bImg) {
+ return getConfig(bImg, 1, 1);
+ }
+
+ public static BufferedImageGraphicsConfig getConfig(BufferedImage bImg,
+ double scaleX,
+ double scaleY)
+ {
BufferedImageGraphicsConfig ret;
int type = bImg.getType();
+
+ BufferedImageGraphicsConfig[] configs = (scaleX == 1 && scaleY == 1)
+ ? standardConfigs : scaledConfigs;
+
if (type > 0 && type < numconfigs) {
ret = configs[type];
- if (ret != null) {
+ if (ret != null && ret.scaleX == scaleX && ret.scaleY == scaleY) {
return ret;
}
}
- ret = new BufferedImageGraphicsConfig(bImg, null);
+ ret = new BufferedImageGraphicsConfig(bImg, null, scaleX, scaleY);
if (type > 0 && type < numconfigs) {
configs[type] = ret;
}
@@ -67,8 +80,16 @@
GraphicsDevice gd;
ColorModel model;
Raster raster;
+ private final double scaleX;
+ private final double scaleY;
public BufferedImageGraphicsConfig(BufferedImage bufImg, Component comp) {
+ this(bufImg, comp, 1, 1);
+ }
+
+ public BufferedImageGraphicsConfig(BufferedImage bufImg, Component comp,
+ double scaleX, double scaleY)
+ {
if (comp == null) {
this.gd = new BufferedImageDevice(this);
} else {
@@ -77,6 +98,8 @@
}
this.model = bufImg.getColorModel();
this.raster = bufImg.getRaster().createCompatibleWritableRaster(1, 1);
+ this.scaleX = scaleX;
+ this.scaleY = scaleY;
}
/**
@@ -138,7 +161,7 @@
* For image buffers, this Transform will be the Identity transform.
*/
public AffineTransform getDefaultTransform() {
- return new AffineTransform();
+ return AffineTransform.getScaleInstance(scaleX, scaleY);
}
/**
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/SunVolatileImage.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/SunVolatileImage.java Tue Nov 17 13:09:16 2015 -0800
@@ -233,8 +233,17 @@
* or a backup surface.
*/
public BufferedImage getBackupImage() {
- return graphicsConfig.createCompatibleImage(getWidth(), getHeight(),
- getTransparency());
+ return getBackupImage(1, 1);
+ }
+
+ /**
+ * This method creates a BufferedImage intended for use as a "snapshot"
+ * or a backup surface with the given horizontal and vertical scale factors.
+ */
+ public BufferedImage getBackupImage(double scaleX, double scaleY) {
+ int w = (int) Math.ceil(getWidth() * scaleX);
+ int h = (int) Math.ceil(getHeight() * scaleY);
+ return graphicsConfig.createCompatibleImage(w, h, getTransparency());
}
public BufferedImage getSnapshot() {
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/SurfaceManager.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/SurfaceManager.java Tue Nov 17 13:09:16 2015 -0800
@@ -290,16 +290,30 @@
}
/**
- * Returns a scale factor of the image. This is utility method, which
- * fetches information from the SurfaceData of the image.
+ * Returns a horizontal scale factor of the image. This is utility method,
+ * which fetches information from the SurfaceData of the image.
*
- * @see SurfaceData#getDefaultScale
+ * @see SurfaceData#getDefaultScaleX
*/
- public static int getImageScale(final Image img) {
+ public static double getImageScaleX(final Image img) {
if (!(img instanceof VolatileImage)) {
return 1;
}
final SurfaceManager sm = getManager(img);
- return sm.getPrimarySurfaceData().getDefaultScale();
+ return sm.getPrimarySurfaceData().getDefaultScaleX();
+ }
+
+ /**
+ * Returns a vertical scale factor of the image. This is utility method,
+ * which fetches information from the SurfaceData of the image.
+ *
+ * @see SurfaceData#getDefaultScaleY
+ */
+ public static double getImageScaleY(final Image img) {
+ if (!(img instanceof VolatileImage)) {
+ return 1;
+ }
+ final SurfaceManager sm = getManager(img);
+ return sm.getPrimarySurfaceData().getDefaultScaleY();
}
}
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/VolatileSurfaceManager.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/VolatileSurfaceManager.java Tue Nov 17 13:09:16 2015 -0800
@@ -25,18 +25,16 @@
package sun.awt.image;
-import java.awt.Color;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.ImageCapabilities;
+import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import sun.awt.DisplayChangedListener;
-import sun.awt.image.SunVolatileImage;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.SurfaceData;
-import sun.java2d.loops.CompositeType;
import static sun.java2d.pipe.hw.AccelSurface.*;
/**
@@ -260,12 +258,16 @@
*/
protected SurfaceData getBackupSurface() {
if (sdBackup == null) {
- BufferedImage bImg = vImg.getBackupImage();
+ GraphicsConfiguration gc = vImg.getGraphicsConfig();
+ AffineTransform tx = gc.getDefaultTransform();
+ double scaleX = tx.getScaleX();
+ double scaleY = tx.getScaleY();
+ BufferedImage bImg = vImg.getBackupImage(scaleX, scaleY);
// Sabotage the acceleration capabilities of the BufImg surface
SunWritableRaster.stealTrackable(bImg
.getRaster()
.getDataBuffer()).setUntrackable();
- sdBackup = BufImgSurfaceData.createData(bImg);
+ sdBackup = BufImgSurfaceData.createData(bImg, scaleX, scaleY);
}
return sdBackup;
}
--- a/jdk/src/java.desktop/share/classes/sun/font/CompositeFont.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/font/CompositeFont.java Tue Nov 17 13:09:16 2015 -0800
@@ -149,6 +149,25 @@
}
}
+ /*
+ * Build a composite from a set of individual slot fonts.
+ */
+ CompositeFont(PhysicalFont[] slotFonts) {
+
+ isStdComposite = false;
+ handle = new Font2DHandle(this);
+ fullName = slotFonts[0].fullName;
+ familyName = slotFonts[0].familyName;
+ style = slotFonts[0].style;
+
+ numMetricsSlots = 1; /* Only the physical Font */
+ numSlots = slotFonts.length;
+
+ components = new PhysicalFont[numSlots];
+ System.arraycopy(slotFonts, 0, components, 0, numSlots);
+ deferredInitialisation = new boolean[numSlots]; // all false.
+ }
+
/* This method is currently intended to be called only from
* FontManager.getCompositeFontUIResource(Font)
* It creates a new CompositeFont with the contents of the Physical
--- a/jdk/src/java.desktop/share/classes/sun/font/CompositeGlyphMapper.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/font/CompositeGlyphMapper.java Tue Nov 17 13:09:16 2015 -0800
@@ -42,7 +42,7 @@
* this appears to cause problems.
*/
-public final class CompositeGlyphMapper extends CharToGlyphMapper {
+public class CompositeGlyphMapper extends CharToGlyphMapper {
public static final int SLOTMASK = 0xff000000;
public static final int GLYPHMASK = 0x00ffffff;
--- a/jdk/src/java.desktop/share/classes/sun/font/Font2D.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/font/Font2D.java Tue Nov 17 13:09:16 2015 -0800
@@ -461,10 +461,17 @@
* to check the font class before attempting to run, rather than needing
* to promote this method up from TrueTypeFont
*/
- byte[] getTableBytes(int tag) {
+ protected byte[] getTableBytes(int tag) {
return null;
}
+ /* implemented for fonts backed by an sfnt that has
+ * OpenType or AAT layout tables.
+ */
+ protected long getLayoutTableCache() {
+ return 0L;
+ }
+
/* for layout code */
protected long getUnitsPerEm() {
return 2048;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/share/classes/sun/font/FontSubstitution.java Tue Nov 17 13:09:16 2015 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015, 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.font;
+
+
+
+/**
+ * Interface that indicates a Font2D that is not a Composite but has the
+ * property that it internally behaves like one, substituting glyphs
+ * from another font at render time.
+ * In this case the Font must provide a way to behave like a regular
+ * composite when that behaviour is not wanted.
+ */
+public interface FontSubstitution {
+ public CompositeFont getCompositeFont2D();
+}
--- a/jdk/src/java.desktop/share/classes/sun/font/GlyphLayout.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/font/GlyphLayout.java Tue Nov 17 13:09:16 2015 -0800
@@ -408,6 +408,9 @@
int lang = -1; // default for now
Font2D font2D = FontUtilities.getFont2D(font);
+ if (font2D instanceof FontSubstitution) {
+ font2D = ((FontSubstitution)font2D).getCompositeFont2D();
+ }
_textRecord.init(text, offset, lim, min, max);
int start = offset;
--- a/jdk/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java Tue Nov 17 13:09:16 2015 -0800
@@ -1124,6 +1124,9 @@
private void initFontData() {
font2D = FontUtilities.getFont2D(font);
+ if (font2D instanceof FontSubstitution) {
+ font2D = ((FontSubstitution)font2D).getCompositeFont2D();
+ }
float s = font.getSize2D();
if (font.isTransformed()) {
ftx = font.getTransform();
@@ -1742,7 +1745,12 @@
aa, fm);
// Get the strike via the handle. Shouldn't matter
// if we've invalidated the font but its an extra precaution.
- FontStrike strike = sgv.font2D.handle.font2D.getStrike(desc); // !!! getStrike(desc, false)
+ // do we want the CompFont from CFont here ?
+ Font2D f2d = sgv.font2D;
+ if (f2d instanceof FontSubstitution) {
+ f2d = ((FontSubstitution)f2d).getCompositeFont2D();
+ }
+ FontStrike strike = f2d.handle.font2D.getStrike(desc); // !!! getStrike(desc, false)
return new GlyphStrike(sgv, strike, dx, dy);
}
--- a/jdk/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/font/SunLayoutEngine.java Tue Nov 17 13:09:16 2015 -0800
@@ -155,10 +155,7 @@
Point2D.Float pt, GVData data) {
Font2D font = key.font();
FontStrike strike = font.getStrike(desc);
- long layoutTables = 0;
- if (font instanceof TrueTypeFont) {
- layoutTables = ((TrueTypeFont) font).getLayoutTableCache();
- }
+ long layoutTables = font.getLayoutTableCache();
nativeLayout(font, strike, mat, gmask, baseIndex,
tr.text, tr.start, tr.limit, tr.min, tr.max,
key.script(), key.lang(), typo_flags, pt, data,
--- a/jdk/src/java.desktop/share/classes/sun/font/TrueTypeFont.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/font/TrueTypeFont.java Tue Nov 17 13:09:16 2015 -0800
@@ -874,8 +874,8 @@
}
}
- /* NB: is it better to move declaration to Font2D? */
- long getLayoutTableCache() {
+ @Override
+ protected long getLayoutTableCache() {
try {
return getScaler().getLayoutTableCache();
} catch(FontScalerException fe) {
@@ -884,7 +884,7 @@
}
@Override
- byte[] getTableBytes(int tag) {
+ protected byte[] getTableBytes(int tag) {
ByteBuffer buffer = getTableBuffer(tag);
if (buffer == null) {
return null;
--- a/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java Tue Nov 17 13:09:16 2015 -0800
@@ -61,7 +61,6 @@
import java.awt.Rectangle;
import java.text.AttributedCharacterIterator;
import java.awt.Font;
-import java.awt.Point;
import java.awt.image.ImageObserver;
import java.awt.Transparency;
import java.awt.font.GlyphVector;
@@ -99,6 +98,7 @@
import static java.awt.geom.AffineTransform.TYPE_FLIP;
import static java.awt.geom.AffineTransform.TYPE_MASK_SCALE;
import static java.awt.geom.AffineTransform.TYPE_TRANSLATION;
+import java.awt.image.VolatileImage;
import sun.awt.image.MultiResolutionToolkitImage;
import sun.awt.image.ToolkitImage;
@@ -3086,30 +3086,50 @@
}
// end of text rendering methods
- private boolean isHiDPIImage(final Image img) {
- return (SurfaceManager.getImageScale(img) != 1)
- || img instanceof MultiResolutionImage;
- }
-
- private boolean drawHiDPIImage(Image img, int dx1, int dy1, int dx2,
- int dy2, int sx1, int sy1, int sx2, int sy2,
- Color bgcolor, ImageObserver observer) {
-
- if (SurfaceManager.getImageScale(img) != 1) { // Volatile Image
- final int scale = SurfaceManager.getImageScale(img);
- sx1 = Region.clipScale(sx1, scale);
- sx2 = Region.clipScale(sx2, scale);
- sy1 = Region.clipScale(sy1, scale);
- sy2 = Region.clipScale(sy2, scale);
- } else if (img instanceof MultiResolutionImage) {
+ private Boolean drawHiDPIImage(Image img,
+ int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2,
+ Color bgcolor, ImageObserver observer,
+ AffineTransform xform) {
+
+ if (img instanceof VolatileImage) {
+ final SurfaceData sd = SurfaceManager.getManager(img)
+ .getPrimarySurfaceData();
+ final double scaleX = sd.getDefaultScaleX();
+ final double scaleY = sd.getDefaultScaleY();
+ if (scaleX == 1 && scaleY == 1) {
+ return null;
+ }
+ sx1 = Region.clipScale(sx1, scaleX);
+ sx2 = Region.clipScale(sx2, scaleX);
+ sy1 = Region.clipScale(sy1, scaleY);
+ sy2 = Region.clipScale(sy2, scaleY);
+
+ AffineTransform tx = null;
+ if (xform != null) {
+ tx = new AffineTransform(transform);
+ transform(xform);
+ }
+ boolean result = scaleImage(img, dx1, dy1, dx2, dy2,
+ sx1, sy1, sx2, sy2,
+ bgcolor, observer);
+ if (tx != null) {
+ transform.setTransform(tx);
+ invalidateTransform();
+ }
+ return result;
+ } else if (resolutionVariantHint != SunHints.INTVAL_RESOLUTION_VARIANT_BASE
+ && (img instanceof MultiResolutionImage)) {
// get scaled destination image size
int width = img.getWidth(observer);
int height = img.getHeight(observer);
- Image resolutionVariant = getResolutionVariant(
- (MultiResolutionImage) img, width, height,
- dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2);
+ MultiResolutionImage mrImage = (MultiResolutionImage) img;
+ Image resolutionVariant = getResolutionVariant(mrImage, width, height,
+ dx1, dy1, dx2, dy2,
+ sx1, sy1, sx2, sy2,
+ xform);
if (resolutionVariant != img && resolutionVariant != null) {
// recalculate source region for the resolution variant
@@ -3123,8 +3143,8 @@
if (0 < width && 0 < height && 0 < rvWidth && 0 < rvHeight) {
- float widthScale = ((float) rvWidth) / width;
- float heightScale = ((float) rvHeight) / height;
+ double widthScale = ((double) rvWidth) / width;
+ double heightScale = ((double) rvHeight) / height;
sx1 = Region.clipScale(sx1, widthScale);
sy1 = Region.clipScale(sy1, heightScale);
@@ -3133,10 +3153,29 @@
observer = rvObserver;
img = resolutionVariant;
+
+ if (xform != null) {
+ assert dx1 == 0 && dy1 == 0;
+ assert dx2 == img.getWidth(observer);
+ assert dy2 == img.getHeight(observer);
+ AffineTransform renderTX = new AffineTransform(xform);
+ renderTX.scale(1 / widthScale, 1 / heightScale);
+ return transformImage(img, renderTX, observer);
+ }
+
+ return scaleImage(img, dx1, dy1, dx2, dy2,
+ sx1, sy1, sx2, sy2,
+ bgcolor, observer);
}
}
}
-
+ return null;
+ }
+
+ private boolean scaleImage(Image img, int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2,
+ Color bgcolor, ImageObserver observer)
+ {
try {
return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1, sy1,
sx2, sy2, bgcolor, observer);
@@ -3156,9 +3195,30 @@
}
}
+ private boolean transformImage(Image img,
+ AffineTransform xform,
+ ImageObserver observer)
+ {
+ try {
+ return imagepipe.transformImage(this, img, xform, observer);
+ } catch (InvalidPipeException e) {
+ try {
+ revalidateAll();
+ return imagepipe.transformImage(this, img, xform, observer);
+ } catch (InvalidPipeException e2) {
+ // Still catching the exception; we are not yet ready to
+ // validate the surfaceData correctly. Fail for now and
+ // try again next time around.
+ return false;
+ }
+ } finally {
+ surfaceData.markDirty();
+ }
+ }
+
private Image getResolutionVariant(MultiResolutionImage img,
int srcWidth, int srcHeight, int dx1, int dy1, int dx2, int dy2,
- int sx1, int sy1, int sx2, int sy2) {
+ int sx1, int sy1, int sx2, int sy2, AffineTransform xform) {
if (srcWidth <= 0 || srcHeight <= 0) {
return null;
@@ -3171,7 +3231,16 @@
return null;
}
- int type = transform.getType();
+ AffineTransform tx;
+
+ if (xform == null) {
+ tx = transform;
+ } else {
+ tx = new AffineTransform(transform);
+ tx.concatenate(xform);
+ }
+
+ int type = tx.getType();
int dw = dx2 - dx1;
int dh = dy2 - dy1;
@@ -3198,13 +3267,13 @@
destRegionWidth = dw;
destRegionHeight = dh;
} else if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP | TYPE_MASK_SCALE)) == 0) {
- destRegionWidth = dw * transform.getScaleX();
- destRegionHeight = dh * transform.getScaleY();
+ destRegionWidth = dw * tx.getScaleX();
+ destRegionHeight = dh * tx.getScaleY();
} else {
destRegionWidth = dw * Math.hypot(
- transform.getScaleX(), transform.getShearY());
+ tx.getScaleX(), tx.getShearY());
destRegionHeight = dh * Math.hypot(
- transform.getShearX(), transform.getScaleY());
+ tx.getShearX(), tx.getScaleY());
}
destImageWidth = Math.abs(srcWidth * destRegionWidth / sw);
destImageHeight = Math.abs(srcHeight * destRegionHeight / sh);
@@ -3277,9 +3346,11 @@
final int imgW = img.getWidth(null);
final int imgH = img.getHeight(null);
- if (isHiDPIImage(img)) {
- return drawHiDPIImage(img, x, y, x + width, y + height, 0, 0, imgW,
- imgH, bg, observer);
+ Boolean hidpiImageDrawn = drawHiDPIImage(img, x, y, x + width, y + height,
+ 0, 0, imgW, imgH, bg, observer,
+ null);
+ if (hidpiImageDrawn != null) {
+ return hidpiImageDrawn;
}
if (width == imgW && height == imgH) {
@@ -3323,11 +3394,13 @@
return true;
}
- if (isHiDPIImage(img)) {
- final int imgW = img.getWidth(null);
- final int imgH = img.getHeight(null);
- return drawHiDPIImage(img, x, y, x + imgW, y + imgH, 0, 0, imgW,
- imgH, bg, observer);
+ final int imgW = img.getWidth(null);
+ final int imgH = img.getHeight(null);
+ Boolean hidpiImageDrawn = drawHiDPIImage(img, x, y, x + imgW, y + imgH,
+ 0, 0, imgW, imgH, bg, observer,
+ null);
+ if (hidpiImageDrawn != null) {
+ return hidpiImageDrawn;
}
try {
@@ -3378,9 +3451,12 @@
return true;
}
- if (isHiDPIImage(img)) {
- return drawHiDPIImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
- bgcolor, observer);
+ Boolean hidpiImageDrawn = drawHiDPIImage(img, dx1, dy1, dx2, dy2,
+ sx1, sy1, sx2, sy2,
+ bgcolor, observer, null);
+
+ if (hidpiImageDrawn != null) {
+ return hidpiImageDrawn;
}
if (((sx2 - sx1) == (dx2 - dx1)) &&
@@ -3461,33 +3537,16 @@
return drawImage(img, 0, 0, null, observer);
}
- if (isHiDPIImage(img)) {
- final int w = img.getWidth(null);
- final int h = img.getHeight(null);
- final AffineTransform tx = new AffineTransform(transform);
- transform(xform);
- boolean result = drawHiDPIImage(img, 0, 0, w, h, 0, 0, w, h, null,
- observer);
- transform.setTransform(tx);
- invalidateTransform();
- return result;
+ final int w = img.getWidth(null);
+ final int h = img.getHeight(null);
+ Boolean hidpiImageDrawn = drawHiDPIImage(img, 0, 0, w, h, 0, 0, w, h,
+ null, observer, xform);
+
+ if (hidpiImageDrawn != null) {
+ return hidpiImageDrawn;
}
- try {
- return imagepipe.transformImage(this, img, xform, observer);
- } catch (InvalidPipeException e) {
- try {
- revalidateAll();
- return imagepipe.transformImage(this, img, xform, observer);
- } catch (InvalidPipeException e2) {
- // Still catching the exception; we are not yet ready to
- // validate the surfaceData correctly. Fail for now and
- // try again next time around.
- return false;
- }
- } finally {
- surfaceData.markDirty();
- }
+ return transformImage(img, xform, observer);
}
public void drawImage(BufferedImage bImg,
--- a/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java Tue Nov 17 13:09:16 2015 -0800
@@ -66,6 +66,8 @@
import sun.font.FontManagerFactory;
import sun.font.FontManagerForSGE;
import sun.font.NativeFont;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
/**
* This is an implementation of a GraphicsEnvironment object for the
@@ -80,6 +82,15 @@
public static boolean isOpenSolaris;
private static Font defaultFont;
+ private static final boolean uiScaleEnabled;
+ private static final double debugScale;
+
+ static {
+ uiScaleEnabled = "true".equals(AccessController.doPrivileged(
+ new GetPropertyAction("sun.java2d.uiScale.enabled", "true")));
+ debugScale = uiScaleEnabled ? getScaleFactor("sun.java2d.uiScale") : -1;
+ }
+
public SunGraphicsEnvironment() {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Object>() {
@@ -341,4 +352,41 @@
public boolean isFlipStrategyPreferred(ComponentPeer peer) {
return false;
}
+
+ public static boolean isUIScaleEnabled() {
+ return uiScaleEnabled;
+ }
+
+ public static double getDebugScale() {
+ return debugScale;
+ }
+
+ public static double getScaleFactor(String propertyName) {
+
+ String scaleFactor = AccessController.doPrivileged(
+ new GetPropertyAction(propertyName, "-1"));
+
+ if (scaleFactor == null || scaleFactor.equals("-1")) {
+ return -1;
+ }
+
+ try {
+ double units = 1.0;
+
+ if (scaleFactor.endsWith("x")) {
+ scaleFactor = scaleFactor.substring(0, scaleFactor.length() - 1);
+ } else if (scaleFactor.endsWith("dpi")) {
+ units = 96;
+ scaleFactor = scaleFactor.substring(0, scaleFactor.length() - 3);
+ } else if (scaleFactor.endsWith("%")) {
+ units = 100;
+ scaleFactor = scaleFactor.substring(0, scaleFactor.length() - 1);
+ }
+
+ double scale = Double.parseDouble(scaleFactor);
+ return scale <= 0 ? -1 : scale / units;
+ } catch (NumberFormatException ignored) {
+ return -1;
+ }
+ }
}
--- a/jdk/src/java.desktop/share/classes/sun/java2d/SurfaceData.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/SurfaceData.java Tue Nov 17 13:09:16 2015 -0800
@@ -1059,12 +1059,22 @@
public abstract Object getDestination();
/**
- * Returns default scale factor of the destination surface. Scale factor
- * describes the mapping between virtual and physical coordinates of the
+ * Returns default horizontal scale factor of the destination surface. Scale
+ * factor describes the mapping between virtual and physical coordinates of the
* SurfaceData. If the scale is 2 then virtual pixel coordinates need to be
* doubled for physical pixels.
*/
- public int getDefaultScale() {
+ public double getDefaultScaleX() {
+ return 1;
+ }
+
+ /**
+ * Returns default vertical scale factor of the destination surface. Scale
+ * factor describes the mapping between virtual and physical coordinates of the
+ * SurfaceData. If the scale is 2 then virtual pixel coordinates need to be
+ * doubled for physical pixels.
+ */
+ public double getDefaultScaleY() {
return 1;
}
}
--- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/DrawImage.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/DrawImage.java Tue Nov 17 13:09:16 2015 -0800
@@ -736,9 +736,10 @@
atfm.scale(m00, m11);
atfm.translate(srcX-sx1, srcY-sy1);
- final int scale = SurfaceManager.getImageScale(img);
- final int imgW = img.getWidth(null) * scale;
- final int imgH = img.getHeight(null) * scale;
+ final double scaleX = SurfaceManager.getImageScaleX(img);
+ final double scaleY = SurfaceManager.getImageScaleY(img);
+ final int imgW = (int) Math.ceil(img.getWidth(null) * scaleX);
+ final int imgH = (int) Math.ceil(img.getHeight(null) * scaleY);
srcW += srcX;
srcH += srcY;
// Make sure we are not out of bounds
--- a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java Tue Nov 17 13:09:16 2015 -0800
@@ -740,7 +740,19 @@
}
updatePageAttributes(service, page);
- PageFormat newPage = pageDialog(attributes);
+ PageFormat newPage = null;
+ DialogTypeSelection dts =
+ (DialogTypeSelection)attributes.get(DialogTypeSelection.class);
+ if (dts == DialogTypeSelection.NATIVE) {
+ // Remove DialogTypeSelection.NATIVE to prevent infinite loop in
+ // RasterPrinterJob.
+ attributes.remove(DialogTypeSelection.class);
+ newPage = pageDialog(attributes);
+ // restore attribute
+ attributes.add(DialogTypeSelection.NATIVE);
+ } else {
+ newPage = pageDialog(attributes);
+ }
if (newPage == null) {
return page;
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java Tue Nov 17 13:09:16 2015 -0800
@@ -80,9 +80,7 @@
pack();
Dimension size = getSize();
- // TODO: When 6356322 is fixed we should get screen bounds in
- // this way: eframe.getGraphicsConfiguration().getBounds().
- Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Rectangle scrSize = getGraphicsConfiguration().getBounds();
if (corner.x < scrSize.width/2 && corner.y < scrSize.height/2) { // 1st square
setLocation(corner.x + indent, corner.y + indent);
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseWindow.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseWindow.java Tue Nov 17 13:09:16 2015 -0800
@@ -300,6 +300,22 @@
}
/**
+ * Returns scale factor of the window. It is used to convert native
+ * coordinates to local and vice verse.
+ */
+ protected int getScale() {
+ return 1;
+ }
+
+ protected int scaleUp(int x) {
+ return x;
+ }
+
+ protected int scaleDown(int x) {
+ return x;
+ }
+
+ /**
* Creates window with parameters specified by <code>params</code>
* @see #init
*/
@@ -366,15 +382,17 @@
log.fine("Creating window for " + this + " with the following attributes: \n" + params);
}
window = XlibWrapper.XCreateWindow(XToolkit.getDisplay(),
- parentWindow.longValue(),
- bounds.x, bounds.y, // location
- bounds.width, bounds.height, // size
- 0, // border
- depth.intValue(), // depth
- visual_class.intValue(), // class
- visual.longValue(), // visual
- value_mask, // value mask
- xattr.pData); // attributes
+ parentWindow.longValue(),
+ scaleUp(bounds.x),
+ scaleUp(bounds.y),
+ scaleUp(bounds.width),
+ scaleUp(bounds.height),
+ 0, // border
+ depth.intValue(), // depth
+ visual_class.intValue(), // class
+ visual.longValue(), // visual
+ value_mask, // value mask
+ xattr.pData); // attributes
if (window == 0) {
throw new IllegalStateException("Couldn't create window because of wrong parameters. Run with NOISY_AWT to see details");
@@ -492,18 +510,18 @@
// we want to reset PPosition in hints. This is necessary
// for locationByPlatform functionality
if ((flags & XUtilConstants.PPosition) != 0) {
- hints.set_x(x);
- hints.set_y(y);
+ hints.set_x(scaleUp(x));
+ hints.set_y(scaleUp(y));
}
if ((flags & XUtilConstants.PSize) != 0) {
- hints.set_width(width);
- hints.set_height(height);
+ hints.set_width(scaleUp(width));
+ hints.set_height(scaleUp(height));
} else if ((hints.get_flags() & XUtilConstants.PSize) != 0) {
flags |= XUtilConstants.PSize;
}
if ((flags & XUtilConstants.PMinSize) != 0) {
- hints.set_min_width(width);
- hints.set_min_height(height);
+ hints.set_min_width(scaleUp(width));
+ hints.set_min_height(scaleUp(height));
} else if ((hints.get_flags() & XUtilConstants.PMinSize) != 0) {
flags |= XUtilConstants.PMinSize;
//Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
@@ -512,31 +530,31 @@
if ((flags & XUtilConstants.PMaxSize) != 0) {
if (maxBounds != null) {
if (maxBounds.width != Integer.MAX_VALUE) {
- hints.set_max_width(maxBounds.width);
+ hints.set_max_width(scaleUp(maxBounds.width));
} else {
hints.set_max_width(XToolkit.getDefaultScreenWidth());
}
if (maxBounds.height != Integer.MAX_VALUE) {
- hints.set_max_height(maxBounds.height);
+ hints.set_max_height(scaleUp(maxBounds.height));
} else {
hints.set_max_height(XToolkit.getDefaultScreenHeight());
}
} else {
- hints.set_max_width(width);
- hints.set_max_height(height);
+ hints.set_max_width(scaleUp(width));
+ hints.set_max_height(scaleUp(height));
}
} else if ((hints.get_flags() & XUtilConstants.PMaxSize) != 0) {
flags |= XUtilConstants.PMaxSize;
if (maxBounds != null) {
if (maxBounds.width != Integer.MAX_VALUE) {
- hints.set_max_width(maxBounds.width);
+ hints.set_max_width(scaleUp(maxBounds.width));
} else {
- hints.set_max_width(XToolkit.getDefaultScreenWidth());
+ hints.set_max_width(scaleUp(XToolkit.getDefaultScreenWidth()));
}
if (maxBounds.height != Integer.MAX_VALUE) {
- hints.set_max_height(maxBounds.height);
+ hints.set_max_height(scaleUp(maxBounds.height));
} else {
- hints.set_max_height(XToolkit.getDefaultScreenHeight());
+ hints.set_max_height(scaleUp(XToolkit.getDefaultScreenHeight()));
}
} else {
// Leave intact
@@ -723,7 +741,9 @@
height = Math.max(MIN_SIZE, height);
XToolkit.awtLock();
try {
- XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), getWindow(), x,y,width,height);
+ XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), getWindow(),
+ scaleUp(x), scaleUp(y),
+ scaleUp(width), scaleUp(height));
} finally {
XToolkit.awtUnlock();
}
@@ -756,7 +776,8 @@
rpt.x = x + srcPeer.getAbsoluteX();
rpt.y = y + srcPeer.getAbsoluteY();
} else {
- rpt = XlibUtil.translateCoordinates(src, dst, new Point(x, y));
+ int scale = srcPeer == null ? 1 : srcPeer.getScale();
+ rpt = XlibUtil.translateCoordinates(src, dst, new Point(x, y), scale);
}
return rpt;
}
@@ -1042,10 +1063,11 @@
if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
insLog.finer("Configure, {0}", xe);
}
- x = xe.get_x();
- y = xe.get_y();
- width = xe.get_width();
- height = xe.get_height();
+
+ x = scaleDown(xe.get_x());
+ y = scaleDown(xe.get_y());
+ width = scaleDown(xe.get_width());
+ height = scaleDown(xe.get_height());
}
/**
* Checks ButtonRelease released all Mouse buttons
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XChoicePeer.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XChoicePeer.java Tue Nov 17 13:09:16 2015 -0800
@@ -785,7 +785,7 @@
numItemsDisplayed = Math.min(MAX_UNFURLED_ITEMS, numItems);
}
Point global = XChoicePeer.this.toGlobal(0,0);
- Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+ Rectangle screen = graphicsConfig.getBounds();
if (alignUnder != null) {
Rectangle choiceRec = XChoicePeer.this.getBounds();
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java Tue Nov 17 13:09:16 2015 -0800
@@ -158,7 +158,9 @@
XComponentPeer newPeer = (XComponentPeer)newNativeParent;
XToolkit.awtLock();
try {
- XlibWrapper.XReparentWindow(XToolkit.getDisplay(), getWindow(), newPeer.getContentWindow(), x, y);
+ XlibWrapper.XReparentWindow(XToolkit.getDisplay(),
+ getWindow(), newPeer.getContentWindow(),
+ scaleUp(x), scaleUp(y));
parentWindow = newPeer;
} finally {
XToolkit.awtUnlock();
@@ -1394,6 +1396,12 @@
XToolkit.awtLock();
try {
if (shape != null) {
+
+ int scale = getScale();
+ if (scale != 1) {
+ shape = shape.getScaledRegion(scale, scale);
+ }
+
XlibWrapper.SetRectangularShape(
XToolkit.getDisplay(),
getWindow(),
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java Tue Nov 17 13:09:16 2015 -0800
@@ -737,16 +737,12 @@
updateChildrenSizes();
- // Bounds of the window
- Rectangle targetBounds = AWTAccessor.getComponentAccessor().getBounds(target);
-
Point newLocation = getNewLocation(xe, currentInsets.left, currentInsets.top);
-
WindowDimensions newDimensions =
new WindowDimensions(newLocation,
- new Dimension(xe.get_width(), xe.get_height()),
- copy(currentInsets),
- true);
+ new Dimension(scaleDown(xe.get_width()),
+ scaleDown(xe.get_height())),
+ copy(currentInsets), true);
if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
insLog.finer("Insets are {0}, new dimensions {1}",
@@ -793,7 +789,8 @@
try {
updateSizeHints(rec.x, rec.y, rec.width, rec.height);
XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), getShell(),
- rec.x, rec.y, rec.width, rec.height);
+ scaleUp(rec.x), scaleUp(rec.y),
+ scaleUp(rec.width), scaleUp(rec.height));
}
finally {
XToolkit.awtUnlock();
@@ -806,7 +803,8 @@
XToolkit.awtLock();
try {
updateSizeHints(rec.x, rec.y, rec.width, rec.height);
- XlibWrapper.XResizeWindow(XToolkit.getDisplay(), getShell(), rec.width, rec.height);
+ XlibWrapper.XResizeWindow(XToolkit.getDisplay(), getShell(),
+ scaleUp(rec.width), scaleUp(rec.height));
}
finally {
XToolkit.awtUnlock();
@@ -819,7 +817,8 @@
XToolkit.awtLock();
try {
updateSizeHints(rec.x, rec.y, rec.width, rec.height);
- XlibWrapper.XMoveWindow(XToolkit.getDisplay(), getShell(), rec.x, rec.y);
+ XlibWrapper.XMoveWindow(XToolkit.getDisplay(), getShell(),
+ scaleUp(rec.x), scaleUp(rec.y));
}
finally {
XToolkit.awtUnlock();
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDragSourceContextPeer.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDragSourceContextPeer.java Tue Nov 17 13:09:16 2015 -0800
@@ -83,6 +83,8 @@
private long[] sourceFormats = null;
/* The XID of the root subwindow that contains the current target. */
private long targetRootSubwindow = 0;
+ /* window scale factor */
+ int windowScale = 1;
/* The pointer location. */
private int xRoot = 0;
private int yRoot = 0;
@@ -130,8 +132,8 @@
long xcursor = 0;
long rootWindow = 0;
- long dragWindow = 0;
long timeStamp = 0;
+ windowScale = wpeer.getScale();
/* Retrieve the X cursor for the drag operation. */
{
@@ -156,8 +158,6 @@
rootWindow = XlibWrapper.RootWindow(XToolkit.getDisplay(), screen);
}
- dragWindow = XWindow.getXAWTRootWindow().getWindow();
-
timeStamp = XToolkit.getCurrentServerTime();
int dropActions = getDragSourceContext().getSourceActions();
@@ -441,8 +441,8 @@
private void updateTargetWindow(XMotionEvent xmotion) {
assert XToolkit.isAWTLockHeldByCurrentThread();
- int x = xmotion.get_x_root();
- int y = xmotion.get_y_root();
+ int x = scaleDown(xmotion.get_x_root());
+ int y = scaleDown(xmotion.get_y_root());
long time = xmotion.get_time();
long subwindow = xmotion.get_subwindow();
@@ -498,9 +498,13 @@
if (!dragInProgress) {
return;
}
- if (xRoot != xmotion.get_x_root() || yRoot != xmotion.get_y_root()) {
- xRoot = xmotion.get_x_root();
- yRoot = xmotion.get_y_root();
+
+ int motionXRoot = scaleDown(xmotion.get_x_root());
+ int motionYRoot = scaleDown(xmotion.get_y_root());
+
+ if (xRoot != motionXRoot || yRoot != motionYRoot) {
+ xRoot = motionXRoot;
+ yRoot = motionYRoot;
postDragSourceDragEvent(targetAction,
XWindow.getModifiers(xmotion.get_state(),0,0),
@@ -519,8 +523,8 @@
updateTargetWindow(xmotion);
if (dragProtocol != null) {
- dragProtocol.sendMoveMessage(xmotion.get_x_root(),
- xmotion.get_y_root(),
+ dragProtocol.sendMoveMessage(scaleDown(xmotion.get_x_root()),
+ scaleDown(xmotion.get_y_root()),
sourceAction, sourceActions,
xmotion.get_time());
}
@@ -528,8 +532,8 @@
private void processDrop(XButtonEvent xbutton) {
try {
- dragProtocol.initiateDrop(xbutton.get_x_root(),
- xbutton.get_y_root(),
+ dragProtocol.initiateDrop(scaleDown(xbutton.get_x_root()),
+ scaleDown(xbutton.get_y_root()),
sourceAction, sourceActions,
xbutton.get_time());
} catch (XException e) {
@@ -805,4 +809,12 @@
dndInProgress = false;
cleanup(XConstants.CurrentTime);
}
+
+ public int scaleUp(int x) {
+ return x * windowScale;
+ }
+
+ public int scaleDown(int x) {
+ return x / windowScale;
+ }
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedClientHelper.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedClientHelper.java Tue Nov 17 13:09:16 2015 -0800
@@ -182,7 +182,7 @@
embedded.notifyStopped();
// check if newParent is a root window
X11GraphicsConfig gc = (X11GraphicsConfig)embedded.getGraphicsConfiguration();
- X11GraphicsDevice gd = (X11GraphicsDevice)gc.getDevice();
+ X11GraphicsDevice gd = gc.getDevice();
if ((newParent == XlibUtil.getRootWindow(gd.getScreen())) ||
(newParent == XToolkit.getDefaultRootWindow()))
{
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbeddedFramePeer.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbeddedFramePeer.java Tue Nov 17 13:09:16 2015 -0800
@@ -146,18 +146,18 @@
// fix for 5063031
// if we use super.handleConfigureNotifyEvent() we would get wrong
// size and position because embedded frame really is NOT a decorated one
- checkIfOnNewScreen(toGlobal(new Rectangle(xe.get_x(),
- xe.get_y(),
- xe.get_width(),
- xe.get_height())));
+ checkIfOnNewScreen(toGlobal(new Rectangle(scaleDown(xe.get_x()),
+ scaleDown(xe.get_y()),
+ scaleDown(xe.get_width()),
+ scaleDown(xe.get_height()))));
Rectangle oldBounds = getBounds();
synchronized (getStateLock()) {
- x = xe.get_x();
- y = xe.get_y();
- width = xe.get_width();
- height = xe.get_height();
+ x = scaleDown(xe.get_x());
+ y = scaleDown(xe.get_y());
+ width = scaleDown(xe.get_width());
+ height = scaleDown(xe.get_height());
dimensions.setClientSize(width, height);
dimensions.setLocation(x, y);
@@ -215,10 +215,10 @@
try {
XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
getWindow(), attr.pData);
- x = attr.get_x();
- y = attr.get_y();
- w = attr.get_width();
- h = attr.get_height();
+ x = scaleDown(attr.get_x());
+ y = scaleDown(attr.get_y());
+ w = scaleDown(attr.get_width());
+ h = scaleDown(attr.get_height());
} finally {
XToolkit.awtUnlock();
}
@@ -276,7 +276,7 @@
{
Point absoluteLoc = XlibUtil.translateCoordinates(getWindow(),
XToolkit.getDefaultRootWindow(),
- new Point(0, 0));
+ new Point(0, 0), getScale());
return absoluteLoc != null ? absoluteLoc.x : 0;
}
@@ -284,7 +284,7 @@
{
Point absoluteLoc = XlibUtil.translateCoordinates(getWindow(),
XToolkit.getDefaultRootWindow(),
- new Point(0, 0));
+ new Point(0, 0), getScale());
return absoluteLoc != null ? absoluteLoc.y : 0;
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuBarPeer.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuBarPeer.java Tue Nov 17 13:09:16 2015 -0800
@@ -296,7 +296,7 @@
*/
protected Rectangle getSubmenuBounds(Rectangle itemBounds, Dimension windowSize) {
Rectangle globalBounds = toGlobal(itemBounds);
- Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Dimension screenSize = graphicsConfig.getBounds().getSize();
Rectangle res;
res = fitWindowBelow(globalBounds, windowSize, screenSize);
if (res != null) {
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuWindow.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuWindow.java Tue Nov 17 13:09:16 2015 -0800
@@ -278,7 +278,7 @@
*/
protected Rectangle getSubmenuBounds(Rectangle itemBounds, Dimension windowSize) {
Rectangle globalBounds = toGlobal(itemBounds);
- Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Dimension screenSize = graphicsConfig.getBounds().getSize();
Rectangle res;
res = fitWindowRight(globalBounds, windowSize, screenSize);
if (res != null) {
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMouseInfoPeer.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMouseInfoPeer.java Tue Nov 17 13:09:16 2015 -0800
@@ -30,6 +30,7 @@
import java.awt.GraphicsEnvironment;
import java.awt.GraphicsDevice;
import java.awt.peer.MouseInfoPeer;
+import sun.awt.X11GraphicsDevice;
import sun.awt.AWTAccessor;
@@ -64,6 +65,12 @@
if (pointerFound) {
point.x = Native.getInt(XlibWrapper.larg3);
point.y = Native.getInt(XlibWrapper.larg4);
+ GraphicsDevice device = gds[i];
+ if (device instanceof X11GraphicsDevice) {
+ int scale = ((X11GraphicsDevice) device).getScaleFactor();
+ point.x = XlibUtil.scaleDown(point.x, scale);
+ point.y = XlibUtil.scaleDown(point.y, scale);
+ }
return i;
}
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XPopupMenuPeer.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XPopupMenuPeer.java Tue Nov 17 13:09:16 2015 -0800
@@ -215,7 +215,7 @@
*/
protected Rectangle getWindowBounds(Point origin, Dimension windowSize) {
Rectangle globalBounds = new Rectangle(origin.x, origin.y, 0, 0);
- Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Dimension screenSize = graphicsConfig.getBounds().getSize();
Rectangle res;
res = fitWindowRight(globalBounds, windowSize, screenSize);
if (res != null) {
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java Tue Nov 17 13:09:16 2015 -0800
@@ -64,7 +64,7 @@
@Override
public void mouseMove(int x, int y) {
- mouseMoveImpl(xgc, x, y);
+ mouseMoveImpl(xgc, xgc.scaleUp(x), xgc.scaleUp(y));
}
@Override
@@ -95,7 +95,8 @@
@Override
public int getRGBPixel(int x, int y) {
int pixelArray[] = new int[1];
- getRGBPixelsImpl(xgc, x, y, 1, 1, pixelArray, isGtkSupported);
+ getRGBPixelsImpl(xgc, x, y, 1, 1, xgc.getScale(), pixelArray,
+ isGtkSupported);
return pixelArray[0];
}
@@ -103,7 +104,7 @@
public int [] getRGBPixels(Rectangle bounds) {
int pixelArray[] = new int[bounds.width*bounds.height];
getRGBPixelsImpl(xgc, bounds.x, bounds.y, bounds.width, bounds.height,
- pixelArray, isGtkSupported);
+ xgc.getScale(), pixelArray, isGtkSupported);
return pixelArray;
}
@@ -118,5 +119,6 @@
private static synchronized native void keyReleaseImpl(int keycode);
private static synchronized native void getRGBPixelsImpl(X11GraphicsConfig xgc,
- int x, int y, int width, int height, int pixelArray[], boolean isGtkSupported);
+ int x, int y, int width, int height, int scale,
+ int pixelArray[], boolean isGtkSupported);
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java Tue Nov 17 13:09:16 2015 -0800
@@ -57,6 +57,7 @@
import sun.security.action.GetPropertyAction;
import sun.security.action.GetBooleanAction;
import sun.util.logging.PlatformLogger;
+import static sun.awt.X11.XlibUtil.scaleDown;
public final class XToolkit extends UNIXToolkit implements Runnable {
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XToolkit");
@@ -422,7 +423,7 @@
}
}
- private void processGlobalMotionEvent(XEvent e) {
+ private void processGlobalMotionEvent(XEvent e, XBaseWindow win) {
// Only our windows guaranteely generate MotionNotify, so we
// should track enter/leave, to catch the moment when to
// switch to XQueryPointer
@@ -431,9 +432,11 @@
awtLock();
try {
if (lastCursorPos == null) {
- lastCursorPos = new Point(ev.get_x_root(), ev.get_y_root());
+ lastCursorPos = new Point(win.scaleDown(ev.get_x_root()),
+ win.scaleDown(ev.get_y_root()));
} else {
- lastCursorPos.setLocation(ev.get_x_root(), ev.get_y_root());
+ lastCursorPos.setLocation(win.scaleDown(ev.get_x_root()),
+ win.scaleDown(ev.get_y_root()));
}
} finally {
awtUnlock();
@@ -452,9 +455,11 @@
awtLock();
try {
if (lastCursorPos == null) {
- lastCursorPos = new Point(ev.get_x_root(), ev.get_y_root());
+ lastCursorPos = new Point(win.scaleDown(ev.get_x_root()),
+ win.scaleDown(ev.get_y_root()));
} else {
- lastCursorPos.setLocation(ev.get_x_root(), ev.get_y_root());
+ lastCursorPos.setLocation(win.scaleDown(ev.get_x_root()),
+ win.scaleDown(ev.get_y_root()));
}
} finally {
awtUnlock();
@@ -492,10 +497,11 @@
private void dispatchEvent(XEvent ev) {
final XAnyEvent xany = ev.get_xany();
- if (windowToXWindow(xany.get_window()) != null &&
- (ev.get_type() == XConstants.MotionNotify || ev.get_type() == XConstants.EnterNotify || ev.get_type() == XConstants.LeaveNotify))
- {
- processGlobalMotionEvent(ev);
+ XBaseWindow baseWindow = windowToXWindow(xany.get_window());
+ if (baseWindow != null && (ev.get_type() == XConstants.MotionNotify
+ || ev.get_type() == XConstants.EnterNotify
+ || ev.get_type() == XConstants.LeaveNotify)) {
+ processGlobalMotionEvent(ev, baseWindow);
}
if( ev.get_type() == XConstants.MappingNotify ) {
@@ -670,8 +676,8 @@
XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
XToolkit.getDefaultRootWindow(),
pattr.pData);
- screenWidth = pattr.get_width();
- screenHeight = pattr.get_height();
+ screenWidth = config.scaleDown(pattr.get_width());
+ screenHeight = config.scaleDown(pattr.get_height());
} finally {
pattr.dispose();
}
@@ -701,7 +707,7 @@
return getDefaultScreenHeight();
}
- private static Rectangle getWorkArea(long root)
+ private static Rectangle getWorkArea(long root, int scale)
{
XAtom XA_NET_WORKAREA = XAtom.get("_NET_WORKAREA");
@@ -717,7 +723,10 @@
int rootWidth = (int)Native.getLong(native_ptr, 2);
int rootHeight = (int)Native.getLong(native_ptr, 3);
- return new Rectangle(rootX, rootY, rootWidth, rootHeight);
+ return new Rectangle(scaleDown(rootX, scale),
+ scaleDown(rootY, scale),
+ scaleDown(rootWidth, scale),
+ scaleDown(rootHeight, scale));
}
}
finally
@@ -750,15 +759,16 @@
try
{
X11GraphicsConfig x11gc = (X11GraphicsConfig)gc;
- X11GraphicsDevice x11gd = (X11GraphicsDevice)x11gc.getDevice();
+ X11GraphicsDevice x11gd = x11gc.getDevice();
long root = XlibUtil.getRootWindow(x11gd.getScreen());
- Rectangle rootBounds = XlibUtil.getWindowGeometry(root);
+ int scale = x11gc.getScale();
+ Rectangle rootBounds = XlibUtil.getWindowGeometry(root, scale);
X11GraphicsEnvironment x11ge = (X11GraphicsEnvironment)
GraphicsEnvironment.getLocalGraphicsEnvironment();
if (!x11ge.runningXinerama())
{
- Rectangle workArea = XToolkit.getWorkArea(root);
+ Rectangle workArea = XToolkit.getWorkArea(root, scale);
if (workArea != null)
{
return new Insets(workArea.y,
@@ -768,7 +778,7 @@
}
}
- return getScreenInsetsManually(root, rootBounds, gc.getBounds());
+ return getScreenInsetsManually(root, rootBounds, gc.getBounds(), scale);
}
finally
{
@@ -783,7 +793,8 @@
*
* This method should be called under XToolkit.awtLock()
*/
- private Insets getScreenInsetsManually(long root, Rectangle rootBounds, Rectangle screenBounds)
+ private Insets getScreenInsetsManually(long root, Rectangle rootBounds,
+ Rectangle screenBounds, int scale)
{
/*
* During the manual calculation of screen insets we iterate
@@ -831,20 +842,23 @@
if (strutPresent)
{
// second, verify that window is located on the proper screen
- Rectangle windowBounds = XlibUtil.getWindowGeometry(window);
+ Rectangle windowBounds = XlibUtil.getWindowGeometry(window,
+ scale);
if (windowLevel > 1)
{
- windowBounds = XlibUtil.translateCoordinates(window, root, windowBounds);
+ windowBounds = XlibUtil.translateCoordinates(window, root,
+ windowBounds,
+ scale);
}
// if _NET_WM_STRUT_PARTIAL is present, we should use its values to detect
// if the struts area intersects with screenBounds, however some window
// managers don't set this hint correctly, so we just get intersection with windowBounds
if (windowBounds != null && windowBounds.intersects(screenBounds))
{
- int left = (int)Native.getLong(native_ptr, 0);
- int right = (int)Native.getLong(native_ptr, 1);
- int top = (int)Native.getLong(native_ptr, 2);
- int bottom = (int)Native.getLong(native_ptr, 3);
+ int left = scaleDown((int)Native.getLong(native_ptr, 0), scale);
+ int right = scaleDown((int)Native.getLong(native_ptr, 1), scale);
+ int top = scaleDown((int)Native.getLong(native_ptr, 2), scale);
+ int bottom = scaleDown((int)Native.getLong(native_ptr, 3), scale);
/*
* struts could be relative to root window bounds, so
@@ -2487,7 +2501,8 @@
oops_updated = false;
long event_number = getEventNumber();
// Generate OOPS ConfigureNotify event
- XlibWrapper.XMoveWindow(getDisplay(), win.getWindow(), ++oops_position, 0);
+ XlibWrapper.XMoveWindow(getDisplay(), win.getWindow(),
+ win.scaleUp(++oops_position), 0);
// Change win position each time to avoid system optimization
if (oops_position > 50) {
oops_position = 0;
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWM.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWM.java Tue Nov 17 13:09:16 2015 -0800
@@ -1024,8 +1024,12 @@
shellBounds.translate(-window.currentInsets.left, -window.currentInsets.top);
window.updateSizeHints(window.getDimensions());
requestWMExtents(window.getWindow());
- XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
- shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
+ XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(),
+ window.getShell(),
+ window.scaleUp(shellBounds.x),
+ window.scaleUp(shellBounds.y),
+ window.scaleUp(shellBounds.width),
+ window.scaleUp(shellBounds.height));
/* REMINDER: will need to revisit when setExtendedStateBounds is added */
//Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
//We need to update frame's minimum size, not to reset it
@@ -1058,8 +1062,12 @@
window.updateSizeHints(newDimensions);
requestWMExtents(window.getWindow());
XToolkit.XSync();
- XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
- shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
+ XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(),
+ window.getShell(),
+ window.scaleUp(shellBounds.x),
+ window.scaleUp(shellBounds.y),
+ window.scaleUp(shellBounds.width),
+ window.scaleUp(shellBounds.height));
}
if (!justChangeSize) { /* update decorations */
setShellDecor(window);
@@ -1701,6 +1709,12 @@
pattr.dispose();
}
}
+
+ correctWM.top = win.scaleUp(correctWM.top);
+ correctWM.bottom = win.scaleUp(correctWM.bottom);
+ correctWM.left = win.scaleUp(correctWM.left);
+ correctWM.right = win.scaleUp(correctWM.right);
+
if (storedInsets.get(win.getClass()) == null) {
storedInsets.put(win.getClass(), correctWM);
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWarningWindow.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWarningWindow.java Tue Nov 17 13:09:16 2015 -0800
@@ -258,10 +258,10 @@
super.handleExposeEvent(xev);
XExposeEvent xe = xev.get_xexpose();
- final int x = xe.get_x();
- final int y = xe.get_y();
- final int width = xe.get_width();
- final int height = xe.get_height();
+ final int x = scaleDown(xe.get_x());
+ final int y = scaleDown(xe.get_y());
+ final int width = scaleDown(xe.get_width());
+ final int height = scaleDown(xe.get_height());
SunToolkit.executeOnEventHandlerThread(target,
new Runnable() {
public void run() {
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java Tue Nov 17 13:09:16 2015 -0800
@@ -548,10 +548,11 @@
if (isEventDisabled(xev)) {
return;
}
- int x = xe.get_x();
- int y = xe.get_y();
- int w = xe.get_width();
- int h = xe.get_height();
+
+ int x = scaleDown(xe.get_x());
+ int y = scaleDown(xe.get_y());
+ int w = scaleDown(xe.get_width());
+ int h = scaleDown(xe.get_height());
Component target = getEventSource();
ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor();
@@ -676,10 +677,11 @@
when = xbe.get_time();
long jWhen = XToolkit.nowMillisUTC_offset(when);
- int x = xbe.get_x();
- int y = xbe.get_y();
+ int x = scaleDown(xbe.get_x());
+ int y = scaleDown(xbe.get_y());
if (xev.get_xany().get_window() != window) {
- Point localXY = toLocal(xbe.get_x_root(), xbe.get_y_root());
+ Point localXY = toLocal(scaleDown(xbe.get_x_root()),
+ scaleDown(xbe.get_y_root()));
x = localXY.x;
y = localXY.y;
}
@@ -730,8 +732,8 @@
MouseEvent me = new MouseEvent(getEventSource(),
type == XConstants.ButtonPress ? MouseEvent.MOUSE_PRESSED : MouseEvent.MOUSE_RELEASED,
jWhen,modifiers, x, y,
- xbe.get_x_root(),
- xbe.get_y_root(),
+ scaleDown(xbe.get_x_root()),
+ scaleDown(xbe.get_y_root()),
clickCount,popupTrigger,button);
postEventToEventQueue(me);
@@ -744,8 +746,8 @@
jWhen,
modifiers,
x, y,
- xbe.get_x_root(),
- xbe.get_y_root(),
+ scaleDown(xbe.get_x_root()),
+ scaleDown(xbe.get_y_root()),
clickCount,
false, button));
}
@@ -757,8 +759,8 @@
MouseWheelEvent mwe = new MouseWheelEvent(getEventSource(),MouseEvent.MOUSE_WHEEL, jWhen,
modifiers,
x, y,
- xbe.get_x_root(),
- xbe.get_y_root(),
+ scaleDown(xbe.get_x_root()),
+ scaleDown(xbe.get_y_root()),
1,false,MouseWheelEvent.WHEEL_UNIT_SCROLL,
3,button==4 ? -1 : 1);
postEventToEventQueue(mwe);
@@ -805,8 +807,8 @@
/*
Fix for 6176814 . Add multiclick checking.
*/
- int x = xme.get_x();
- int y = xme.get_y();
+ int x = scaleDown(xme.get_x());
+ int y = scaleDown(xme.get_y());
XWindow lastWindow = (lastWindowRef != null) ? (lastWindowRef.get()):(null);
if (!(lastWindow == this &&
@@ -828,7 +830,8 @@
Component source = getEventSource();
if (xme.get_window() != window) {
- Point localXY = toLocal(xme.get_x_root(), xme.get_y_root());
+ Point localXY = toLocal(scaleDown(xme.get_x_root()),
+ scaleDown(xme.get_y_root()));
x = localXY.x;
y = localXY.y;
}
@@ -837,7 +840,9 @@
*/
if ((isDragging && clickCount == 0) || !isDragging) {
MouseEvent mme = new MouseEvent(source, mouseEventType, jWhen,
- modifiers, x, y, xme.get_x_root(), xme.get_y_root(),
+ modifiers, x, y,
+ scaleDown(xme.get_x_root()),
+ scaleDown(xme.get_y_root()),
clickCount, popupTrigger, MouseEvent.NOBUTTON);
postEventToEventQueue(mme);
}
@@ -949,10 +954,11 @@
int modifiers = getModifiers(xce.get_state(),0,0);
int clickCount = 0;
boolean popupTrigger = false;
- int x = xce.get_x();
- int y = xce.get_y();
+ int x = scaleDown(xce.get_x());
+ int y = scaleDown(xce.get_y());
if (xce.get_window() != window) {
- Point localXY = toLocal(xce.get_x_root(), xce.get_y_root());
+ Point localXY = toLocal(scaleDown(xce.get_x_root()),
+ scaleDown(xce.get_y_root()));
x = localXY.x;
y = localXY.y;
}
@@ -960,18 +966,27 @@
// This code tracks boundary crossing and ensures MOUSE_ENTER/EXIT
// are posted in alternate pairs
if (compWithMouse != null) {
- MouseEvent me = new MouseEvent(compWithMouse,
- MouseEvent.MOUSE_EXITED, jWhen, modifiers, xce.get_x(),
- xce.get_y(), xce.get_x_root(), xce.get_y_root(), clickCount, popupTrigger,
- MouseEvent.NOBUTTON);
+ MouseEvent me = new MouseEvent(compWithMouse, MouseEvent.MOUSE_EXITED,
+ jWhen, modifiers,
+ scaleDown(xce.get_x()),
+ scaleDown(xce.get_y()),
+ scaleDown(xce.get_x_root()),
+ scaleDown(xce.get_y_root()),
+ clickCount, popupTrigger,
+ MouseEvent.NOBUTTON);
postEventToEventQueue(me);
eventLog.finest("Clearing last window ref");
lastWindowRef = null;
}
if (xce.get_type() == XConstants.EnterNotify) {
MouseEvent me = new MouseEvent(getEventSource(), MouseEvent.MOUSE_ENTERED,
- jWhen, modifiers, xce.get_x(), xce.get_y(), xce.get_x_root(), xce.get_y_root(), clickCount,
- popupTrigger, MouseEvent.NOBUTTON);
+ jWhen, modifiers,
+ scaleDown(xce.get_x()),
+ scaleDown(xce.get_y()),
+ scaleDown(xce.get_x_root()),
+ scaleDown(xce.get_y_root()),
+ clickCount, popupTrigger,
+ MouseEvent.NOBUTTON);
postEventToEventQueue(me);
}
}
@@ -1531,4 +1546,18 @@
}
}
+ @Override
+ protected int getScale() {
+ return graphicsConfig.getScale();
+ }
+
+ @Override
+ protected int scaleUp(int x) {
+ return graphicsConfig.scaleUp(x);
+ }
+
+ @Override
+ protected int scaleDown(int x) {
+ return graphicsConfig.scaleDown(x);
+ }
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java Tue Nov 17 13:09:16 2015 -0800
@@ -29,6 +29,7 @@
import java.awt.event.ComponentEvent;
import java.awt.event.FocusEvent;
import java.awt.event.WindowEvent;
+import java.awt.geom.AffineTransform;
import java.awt.peer.ComponentPeer;
import java.awt.peer.WindowPeer;
@@ -750,10 +751,10 @@
private Point queryXLocation()
{
- return XlibUtil.translateCoordinates(
- getContentWindow(),
- XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber()),
- new Point(0, 0));
+ return XlibUtil.translateCoordinates(getContentWindow(), XlibWrapper
+ .RootWindow(XToolkit.getDisplay(),
+ getScreenNumber()),
+ new Point(0, 0), getScale());
}
protected Point getNewLocation(XConfigureEvent xe, int leftInset, int topInset) {
@@ -764,7 +765,8 @@
Point newLocation = targetBounds.getLocation();
if (xe.get_send_event() || runningWM == XWM.NO_WM || XWM.isNonReparentingWM()) {
// Location, Client size + insets
- newLocation = new Point(xe.get_x() - leftInset, xe.get_y() - topInset);
+ newLocation = new Point(scaleDown(xe.get_x()) - leftInset,
+ scaleDown(xe.get_y()) - topInset);
} else {
// ICCCM 4.1.5 states that a real ConfigureNotify will be sent when
// a window is resized but the client can not tell if the window was
@@ -807,12 +809,12 @@
* See getNewLocation() for the details.
*/
Point newLocation = getNewLocation(xe, 0, 0);
- xe.set_x(newLocation.x);
- xe.set_y(newLocation.y);
- checkIfOnNewScreen(new Rectangle(xe.get_x(),
- xe.get_y(),
- xe.get_width(),
- xe.get_height()));
+ xe.set_x(scaleUp(newLocation.x));
+ xe.set_y(scaleUp(newLocation.y));
+ checkIfOnNewScreen(new Rectangle(newLocation.x,
+ newLocation.y,
+ scaleDown(xe.get_width()),
+ scaleDown(xe.get_height())));
// Don't call super until we've handled a screen change. Otherwise
// there could be a race condition in which a ComponentListener could
@@ -2115,7 +2117,9 @@
XCrossingEvent xce = xev.get_xcrossing();
if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
grabLog.fine("{0}, when grabbed {1}, contains {2}",
- xce, isGrabbed(), containsGlobal(xce.get_x_root(), xce.get_y_root()));
+ xce, isGrabbed(),
+ containsGlobal(scaleDown(xce.get_x_root()),
+ scaleDown(xce.get_y_root())));
}
if (isGrabbed()) {
// When window is grabbed, all events are dispatched to
@@ -2141,7 +2145,9 @@
XMotionEvent xme = xev.get_xmotion();
if (grabLog.isLoggable(PlatformLogger.Level.FINER)) {
grabLog.finer("{0}, when grabbed {1}, contains {2}",
- xme, isGrabbed(), containsGlobal(xme.get_x_root(), xme.get_y_root()));
+ xme, isGrabbed(),
+ containsGlobal(scaleDown(xme.get_x_root()),
+ scaleDown(xme.get_y_root())));
}
if (isGrabbed()) {
boolean dragging = false;
@@ -2166,9 +2172,10 @@
// So, I do not want to implement complicated logic for better retargeting.
target = pressTarget.isVisible() ? pressTarget : this;
xme.set_window(target.getWindow());
- Point localCoord = target.toLocal(xme.get_x_root(), xme.get_y_root());
- xme.set_x(localCoord.x);
- xme.set_y(localCoord.y);
+ Point localCoord = target.toLocal(scaleDown(xme.get_x_root()),
+ scaleDown(xme.get_y_root()));
+ xme.set_x(scaleUp(localCoord.x));
+ xme.set_y(scaleUp(localCoord.y));
}
if (grabLog.isLoggable(PlatformLogger.Level.FINER)) {
grabLog.finer(" - Grab event target {0}", target);
@@ -2182,7 +2189,9 @@
// note that we need to pass dragging events to the grabber (6390326)
// see comment above for more inforamtion.
- if (!containsGlobal(xme.get_x_root(), xme.get_y_root()) && !dragging) {
+ if (!containsGlobal(scaleDown(xme.get_x_root()),
+ scaleDown(xme.get_y_root()))
+ && !dragging) {
// Outside of Java
return;
}
@@ -2195,7 +2204,6 @@
public void handleButtonPressRelease(XEvent xev) {
XButtonEvent xbe = xev.get_xbutton();
-
/*
* Ignore the buttons above 20 due to the bit limit for
* InputEvent.BUTTON_DOWN_MASK.
@@ -2206,7 +2214,11 @@
}
if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
grabLog.fine("{0}, when grabbed {1}, contains {2} ({3}, {4}, {5}x{6})",
- xbe, isGrabbed(), containsGlobal(xbe.get_x_root(), xbe.get_y_root()), getAbsoluteX(), getAbsoluteY(), getWidth(), getHeight());
+ xbe, isGrabbed(),
+ containsGlobal(scaleDown(xbe.get_x_root()),
+ scaleDown(xbe.get_y_root())),
+ getAbsoluteX(), getAbsoluteY(),
+ getWidth(), getHeight());
}
if (isGrabbed()) {
// When window is grabbed, all events are dispatched to
@@ -2232,9 +2244,10 @@
// see 6390326 for more information.
target = pressTarget.isVisible() ? pressTarget : this;
xbe.set_window(target.getWindow());
- Point localCoord = target.toLocal(xbe.get_x_root(), xbe.get_y_root());
- xbe.set_x(localCoord.x);
- xbe.set_y(localCoord.y);
+ Point localCoord = target.toLocal(scaleDown(xbe.get_x_root()),
+ scaleDown(xbe.get_y_root()));
+ xbe.set_x(scaleUp(localCoord.x));
+ xbe.set_y(scaleUp(localCoord.y));
pressTarget = this;
}
if (target != null && target != getContentXWindow() && target != this) {
@@ -2246,7 +2259,10 @@
// Target is either us or our content window -
// check that event is inside. 'Us' in case of
// shell will mean that this will also filter out press on title
- if ((target == this || target == getContentXWindow()) && !containsGlobal(xbe.get_x_root(), xbe.get_y_root())) {
+ if ((target == this || target == getContentXWindow())
+ && !containsGlobal(scaleDown(xbe.get_x_root()),
+ scaleDown(xbe.get_y_root())))
+ {
// Outside this toplevel hierarchy
// According to the specification of UngrabEvent, post it
// when press occurs outside of the window and not on its owned windows
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XlibUtil.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XlibUtil.java Tue Nov 17 13:09:16 2015 -0800
@@ -102,7 +102,7 @@
/**
* Returns the bounds of the given window, in absolute coordinates
*/
- static Rectangle getWindowGeometry(long window)
+ static Rectangle getWindowGeometry(long window, int scale)
{
XToolkit.awtLock();
try
@@ -126,7 +126,9 @@
long width = Native.getUInt(XlibWrapper.larg4);
long height = Native.getUInt(XlibWrapper.larg5);
- return new Rectangle(x, y, (int)width, (int)height);
+ return new Rectangle(scaleDown(x, scale), scaleDown(y, scale),
+ scaleDown((int) width, scale),
+ scaleDown((int) height, scale));
}
finally
{
@@ -138,7 +140,7 @@
* Translates the given point from one window to another. Returns
* null if the translation is failed
*/
- static Point translateCoordinates(long src, long dst, Point p)
+ static Point translateCoordinates(long src, long dst, Point p, int scale)
{
Point translated = null;
@@ -146,7 +148,7 @@
try
{
XTranslateCoordinates xtc =
- new XTranslateCoordinates(src, dst, p.x, p.y);
+ new XTranslateCoordinates(src, dst, p.x * scale, p.y * scale);
try
{
int status = xtc.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
@@ -154,7 +156,8 @@
((XErrorHandlerUtil.saved_error == null) ||
(XErrorHandlerUtil.saved_error.get_error_code() == XConstants.Success)))
{
- translated = new Point(xtc.get_dest_x(), xtc.get_dest_y());
+ translated = new Point(scaleDown(xtc.get_dest_x(), scale),
+ scaleDown(xtc.get_dest_y(), scale));
}
}
finally
@@ -174,9 +177,12 @@
* Translates the given rectangle from one window to another.
* Returns null if the translation is failed
*/
- static Rectangle translateCoordinates(long src, long dst, Rectangle r)
+ static Rectangle translateCoordinates(long src, long dst, Rectangle r,
+ int scale)
{
- Point translatedLoc = translateCoordinates(src, dst, r.getLocation());
+ Point translatedLoc = translateCoordinates(src, dst, r.getLocation(),
+ scale);
+
if (translatedLoc == null)
{
return null;
@@ -406,4 +412,8 @@
return 1 << (7 + button);
}
}
+
+ static int scaleDown(int x, int scale) {
+ return x / scale;
+ }
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsConfig.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsConfig.java Tue Nov 17 13:09:16 2015 -0800
@@ -133,7 +133,7 @@
/**
* Return the graphics device associated with this configuration.
*/
- public GraphicsDevice getDevice() {
+ public X11GraphicsDevice getDevice() {
return screen;
}
@@ -256,7 +256,20 @@
* For image buffers, this Transform will be the Identity transform.
*/
public AffineTransform getDefaultTransform() {
- return new AffineTransform();
+ double scale = getScale();
+ return AffineTransform.getScaleInstance(scale, scale);
+ }
+
+ public int getScale() {
+ return getDevice().getScaleFactor();
+ }
+
+ public int scaleUp(int x) {
+ return x * getScale();
+ }
+
+ public int scaleDown(int x) {
+ return x / getScale();
}
/**
@@ -308,7 +321,14 @@
}
public Rectangle getBounds() {
- return pGetBounds(screen.getScreen());
+ Rectangle rect = pGetBounds(screen.getScreen());
+ if (getScale() != 1) {
+ rect.x = scaleDown(rect.x);
+ rect.y = scaleDown(rect.y);
+ rect.width = scaleDown(rect.width);
+ rect.height = scaleDown(rect.height);
+ }
+ return rect;
}
private native Rectangle pGetBounds(int screenNum);
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java Tue Nov 17 13:09:16 2015 -0800
@@ -43,6 +43,7 @@
import sun.java2d.loops.SurfaceType;
import sun.awt.util.ThreadGroupUtils;
+import sun.java2d.SunGraphicsEnvironment;
import sun.misc.ManagedLocalsThread;
/**
@@ -63,9 +64,11 @@
private SunDisplayChanger topLevels = new SunDisplayChanger();
private DisplayMode origDisplayMode;
private boolean shutdownHookRegistered;
+ private final int scale;
public X11GraphicsDevice(int screennum) {
this.screen = screennum;
+ this.scale = initScaleFactor();
}
/*
@@ -279,6 +282,7 @@
int width, int height,
int displayMode);
private static native void resetNativeData(int screen);
+ private static native int getNativeScaleFactor(int screen);
/**
* Returns true only if:
@@ -509,6 +513,27 @@
topLevels.add(client);
}
+ public int getScaleFactor() {
+ return scale;
+ }
+
+ private int initScaleFactor() {
+
+ if (SunGraphicsEnvironment.isUIScaleEnabled()) {
+
+ double debugScale = SunGraphicsEnvironment.getDebugScale();
+
+ if (debugScale >= 1) {
+ return (int) debugScale;
+ }
+
+ int nativeScale = getNativeScaleFactor(screen);
+ return nativeScale >= 1 ? nativeScale : 1;
+ }
+
+ return 1;
+ }
+
/**
* Remove a DisplayChangeListener from this X11GraphicsDevice.
*/
--- a/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceData.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceData.java Tue Nov 17 13:09:16 2015 -0800
@@ -244,7 +244,8 @@
int width, int height,
ColorModel cm, Image image,
long drawable,
- int transparency) {
+ int transparency,
+ boolean isTexture) {
int depth;
// If we have a 32 bit color model for the window it needs
// alpha to support translucency of the window so we need
@@ -267,7 +268,7 @@
return new XRPixmapSurfaceData
(gc, width, height, image, getSurfaceType(gc, transparency),
cm, drawable, transparency,
- XRUtils.getPictureFormatForTransparency(transparency), depth);
+ XRUtils.getPictureFormatForTransparency(transparency), depth, isTexture);
}
protected XRSurfaceData(X11ComponentPeer peer, XRGraphicsConfig gc,
@@ -542,11 +543,16 @@
}
public static class XRWindowSurfaceData extends XRSurfaceData {
+
+ protected final int scale;
+
public XRWindowSurfaceData(X11ComponentPeer peer,
XRGraphicsConfig gc, SurfaceType sType) {
super(peer, gc, sType, peer.getColorModel(),
peer.getColorModel().getPixelSize(), Transparency.OPAQUE);
+ this.scale = gc.getScale();
+
if (isXRDrawableValid()) {
// If we have a 32 bit color model for the window it needs
// alpha to support translucency of the window so we need
@@ -571,6 +577,8 @@
public Rectangle getBounds() {
Rectangle r = peer.getBounds();
r.x = r.y = 0;
+ r.width *= scale;
+ r.height *= scale;
return r;
}
@@ -596,6 +604,16 @@
super.invalidate();
}
+
+ @Override
+ public double getDefaultScaleX() {
+ return scale;
+ }
+
+ @Override
+ public double getDefaultScaleY() {
+ return scale;
+ }
}
public static class XRInternalSurfaceData extends XRSurfaceData {
@@ -627,18 +645,20 @@
int width;
int height;
int transparency;
+ private final int scale;
public XRPixmapSurfaceData(XRGraphicsConfig gc, int width, int height,
Image image, SurfaceType sType,
ColorModel cm, long drawable,
int transparency, int pictFormat,
- int depth) {
+ int depth, boolean isTexture) {
super(null, gc, sType, cm, depth, transparency);
- this.width = width;
- this.height = height;
+ this.scale = isTexture ? 1 : gc.getDevice().getScaleFactor();
+ this.width = width * scale;
+ this.height = height * scale;
offscreenImage = image;
this.transparency = transparency;
- initSurface(depth, width, height, drawable, pictFormat);
+ initSurface(depth, this.width, this.height, drawable, pictFormat);
initXRender(pictFormat);
makePipes();
@@ -696,6 +716,16 @@
public Object getDestination() {
return offscreenImage;
}
+
+ @Override
+ public double getDefaultScaleX() {
+ return scale;
+ }
+
+ @Override
+ public double getDefaultScaleY() {
+ return scale;
+ }
}
public long getGC() {
--- a/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceDataProxy.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceDataProxy.java Tue Nov 17 13:09:16 2015 -0800
@@ -59,8 +59,9 @@
public SurfaceData validateSurfaceData(SurfaceData srcData,
SurfaceData cachedData, int w, int h) {
if (cachedData == null) {
- cachedData = XRSurfaceData.createData(xrgc, w, h, xrgc
- .getColorModel(), null, 0, getTransparency());
+ cachedData = XRSurfaceData.createData(xrgc, w, h,
+ xrgc.getColorModel(), null, 0,
+ getTransparency(), true);
}
return cachedData;
}
--- a/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRVolatileSurfaceManager.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/java2d/xr/XRVolatileSurfaceManager.java Tue Nov 17 13:09:16 2015 -0800
@@ -59,10 +59,10 @@
drawable = ((Long)context).longValue();
}
sData = XRSurfaceData.createData(gc,
- vImg.getWidth(),
- vImg.getHeight(),
- cm, vImg, drawable,
- vImg.getTransparency());
+ vImg.getWidth(),
+ vImg.getHeight(),
+ cm, vImg, drawable,
+ vImg.getTransparency(), false);
} catch (NullPointerException ex) {
sData = null;
} catch (OutOfMemoryError er) {
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c Tue Nov 17 13:09:16 2015 -0800
@@ -2082,3 +2082,38 @@
/**
* End DisplayMode/FullScreen support
*/
+
+int getScale(const char *name) {
+ char *uiScale = getenv(name);
+ if (uiScale != NULL) {
+ double scale = strtod(uiScale, NULL);
+ if (errno == ERANGE || scale < 1) {
+ return -1;
+ }
+ return (int) scale;
+ }
+ return -1;
+}
+
+/*
+ * Class: sun_awt_X11GraphicsDevice
+ * Method: getNativeScaleFactor
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL
+Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor
+ (JNIEnv *env, jobject this, jint screen) {
+
+ // for debug purposes
+ static int scale = -2.0;
+
+ if (scale == -2) {
+ scale = getScale("J2D_UISCALE");
+ }
+
+ if (scale >= 1) {
+ return scale;
+ }
+
+ return getScale("GDK_SCALE");
+}
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c Tue Nov 17 13:09:16 2015 -0800
@@ -210,6 +210,7 @@
jint jy,
jint jwidth,
jint jheight,
+ jint scale,
jintArray pixelArray,
jboolean isGtkSupported) {
XImage *image;
@@ -231,13 +232,18 @@
AWT_LOCK();
+ jint sx = jx * scale;
+ jint sy = jy * scale;
+ jint swidth = jwidth * scale;
+ jint sheight = jheight * scale;
+
rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
if (!XGetWindowAttributes(awt_display, rootWindow, &attr)
- || jx + jwidth <= attr.x
- || attr.x + attr.width <= jx
- || jy + jheight <= attr.y
- || attr.y + attr.height <= jy) {
+ || sx + swidth <= attr.x
+ || attr.x + attr.width <= sx
+ || sy + sheight <= attr.y
+ || attr.y + attr.height <= sy) {
AWT_UNLOCK();
return; // Does not intersect with root window
@@ -246,14 +252,14 @@
gboolean gtk_failed = TRUE;
jint _x, _y;
- jint x = MAX(jx, attr.x);
- jint y = MAX(jy, attr.y);
- jint width = MIN(jx + jwidth, attr.x + attr.width) - x;
- jint height = MIN(jy + jheight, attr.y + attr.height) - y;
+ jint x = MAX(sx, attr.x);
+ jint y = MAX(sy, attr.y);
+ jint width = MIN(sx + swidth, attr.x + attr.width) - x;
+ jint height = MIN(sy + sheight, attr.y + attr.height) - y;
- int dx = attr.x > jx ? attr.x - jx : 0;
- int dy = attr.y > jy ? attr.y - jy : 0;
+ int dx = attr.x > sx ? attr.x - sx : 0;
+ int dy = attr.y > sy ? attr.y - sy : 0;
int index;
@@ -264,6 +270,19 @@
pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL,
x, y, 0, 0, width, height);
+ if (pixbuf && scale != 1) {
+ GdkPixbuf *scaledPixbuf;
+ x /= scale;
+ y /= scale;
+ width /= scale;
+ height /= scale;
+ dx /= scale;
+ dy /= scale;
+ scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height,
+ GDK_INTERP_BILINEAR);
+ (*fp_g_object_unref)(pixbuf);
+ pixbuf = scaledPixbuf;
+ }
if (pixbuf) {
int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
@@ -312,7 +331,7 @@
}
if (gtk_failed) {
- image = getWindowImage(awt_display, rootWindow, x, y, width, height);
+ image = getWindowImage(awt_display, rootWindow, sx, sy, swidth, sheight);
ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);
@@ -322,10 +341,16 @@
return;
}
+ dx /= scale;
+ dy /= scale;
+ width /= scale;
+ height /= scale;
+
/* convert to Java ARGB pixels */
for (_y = 0; _y < height; _y++) {
for (_x = 0; _x < width; _x++) {
- jint pixel = (jint) XGetPixel(image, _x, _y); /* Note ignore upper
+ jint pixel = (jint) XGetPixel(image, _x * scale, _y * scale);
+ /* Note ignore upper
* 32-bits on 64-bit
* OSes.
*/
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c Tue Nov 17 13:09:16 2015 -0800
@@ -648,6 +648,8 @@
fp_gdk_pixmap_new = dl_symbol("gdk_pixmap_new");
fp_gdk_pixbuf_get_from_drawable =
dl_symbol("gdk_pixbuf_get_from_drawable");
+ fp_gdk_pixbuf_scale_simple =
+ dl_symbol("gdk_pixbuf_scale_simple");
fp_gdk_gc_new = dl_symbol("gdk_gc_new");
fp_gdk_rgb_gc_set_foreground =
dl_symbol("gdk_rgb_gc_set_foreground");
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h Tue Nov 17 13:09:16 2015 -0800
@@ -270,6 +270,13 @@
G_PARAM_PRIVATE = 1 << 5
} GParamFlags;
+typedef enum {
+ GDK_INTERP_NEAREST,
+ GDK_INTERP_TILES,
+ GDK_INTERP_BILINEAR,
+ GDK_INTERP_HYPER
+} GdkInterpType;
+
/* We define all structure pointers to be void* */
typedef void GError;
typedef void GMainContext;
@@ -787,6 +794,8 @@
GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkPixbuf *dest,
GdkDrawable *src, GdkColormap *cmap, int src_x, int src_y,
int dest_x, int dest_y, int width, int height);
+GdkPixbuf *(*fp_gdk_pixbuf_scale_simple)(GdkPixbuf *src,
+ int dest_width, int dest_heigh, GdkInterpType interp_type);
void (*fp_gtk_widget_destroy)(GtkWidget *widget);
--- a/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsConfig.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsConfig.java Tue Nov 17 13:09:16 2015 -0800
@@ -106,7 +106,7 @@
/**
* Return the graphics device associated with this configuration.
*/
- public GraphicsDevice getDevice() {
+ public Win32GraphicsDevice getDevice() {
return screen;
}
@@ -182,7 +182,9 @@
* For image buffers, this Transform will be the Identity transform.
*/
public AffineTransform getDefaultTransform() {
- return new AffineTransform();
+ double scaleX = screen.getDefaultScaleX();
+ double scaleY = screen.getDefaultScaleY();
+ return AffineTransform.getScaleInstance(scaleX, scaleY);
}
/**
--- a/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java Tue Nov 17 13:09:16 2015 -0800
@@ -37,13 +37,19 @@
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
+import java.awt.geom.Point2D;
import java.awt.image.ColorModel;
import java.util.ArrayList;
import java.util.Vector;
import java.awt.peer.WindowPeer;
+import java.security.AccessController;
import sun.awt.windows.WWindowPeer;
+import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.opengl.WGLGraphicsConfig;
import sun.java2d.windows.WindowsFlags;
+import sun.security.action.GetPropertyAction;
+import static sun.awt.Win32GraphicsEnvironment.debugScaleX;
+import static sun.awt.Win32GraphicsEnvironment.debugScaleY;
/**
* This is an implementation of a GraphicsDevice object for a single
@@ -81,6 +87,9 @@
// activation/deactivation listener for the full-screen window
private WindowListener fsWindowListener;
+ private float scaleX;
+ private float scaleY;
+
static {
// 4455041 - Even when ddraw is disabled, ddraw.dll is loaded when
@@ -97,6 +106,10 @@
private static native void initIDs();
native void initDevice(int screen);
+ native void initNativeScale(int screen);
+ native void setNativeScale(int screen, float scaleX, float scaleY);
+ native float getNativeScaleX(int screen);
+ native float getNativeScaleY(int screen);
public Win32GraphicsDevice(int screennum) {
this.screen = screennum;
@@ -109,6 +122,7 @@
valid = true;
initDevice(screennum);
+ initScaleFactors();
}
/**
@@ -128,6 +142,31 @@
return screen;
}
+ public float getDefaultScaleX() {
+ return scaleX;
+ }
+
+ public float getDefaultScaleY() {
+ return scaleY;
+ }
+
+ private void initScaleFactors() {
+ if (SunGraphicsEnvironment.isUIScaleEnabled()) {
+ if (debugScaleX > 0 && debugScaleY > 0) {
+ scaleX = debugScaleX;
+ scaleY = debugScaleY;
+ setNativeScale(screen, scaleX, scaleY);
+ } else {
+ initNativeScale(screen);
+ scaleX = getNativeScaleX(screen);
+ scaleY = getNativeScaleY(screen);
+ }
+ } else {
+ scaleX = 1;
+ scaleY = 1;
+ }
+ }
+
/**
* Returns whether this is a valid devicie. Device can become
* invalid as a result of device removal event.
@@ -486,6 +525,7 @@
configs = null;
// pass on to all top-level windows on this display
topLevels.notifyListeners();
+ initScaleFactors();
}
/**
--- a/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsEnvironment.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsEnvironment.java Tue Nov 17 13:09:16 2015 -0800
@@ -51,6 +51,9 @@
public final class Win32GraphicsEnvironment extends SunGraphicsEnvironment {
+ static final float debugScaleX;
+ static final float debugScaleY;
+
static {
// Ensure awt is loaded already. Also, this forces static init
// of WToolkit and Toolkit, which we depend upon
@@ -61,6 +64,21 @@
// Install correct surface manager factory.
SurfaceManagerFactory.setInstance(new WindowsSurfaceManagerFactory());
+
+ double sx = -1;
+ double sy = -1;
+ if (isUIScaleEnabled()) {
+ sx = getScaleFactor("sun.java2d.win.uiScaleX");
+ sy = getScaleFactor("sun.java2d.win.uiScaleY");
+ if (sx <= 0 || sy <= 0) {
+ double s = getDebugScale();
+ sx = s;
+ sy = s;
+ }
+ }
+
+ debugScaleX = (float) sx;
+ debugScaleY = (float) sy;
}
/**
--- a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java Tue Nov 17 13:09:16 2015 -0800
@@ -141,6 +141,9 @@
public static final int SHGDN_FORADDRESSBAR = 0x4000;
public static final int SHGDN_FORPARSING = 0x8000;
+ /** The referent to be registered with the Disposer. */
+ private Object disposerReferent = new Object();
+
// Values for system call LoadIcon()
public enum SystemIcon {
IDI_APPLICATION(32512),
@@ -297,7 +300,7 @@
}
}, InterruptedException.class);
- sun.java2d.Disposer.addRecord(this, disposer);
+ sun.java2d.Disposer.addObjectRecord(disposerReferent, disposer);
}
@@ -309,7 +312,7 @@
this.isLib = isLib;
this.disposer.pIShellFolder = pIShellFolder;
this.disposer.relativePIDL = relativePIDL;
- sun.java2d.Disposer.addRecord(this, disposer);
+ sun.java2d.Disposer.addObjectRecord(disposerReferent, disposer);
}
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java Tue Nov 17 13:09:16 2015 -0800
@@ -294,6 +294,12 @@
synchronized native void reshapeFrame(int x, int y, int width, int height);
+ native Dimension getNativeWindowSize();
+
+ public Dimension getScaledWindowSize() {
+ return getNativeWindowSize();
+ }
+
public boolean requestWindowFocus(CausedFocusEvent.Cause cause) {
if (!focusAllowedFor()) {
return false;
@@ -490,8 +496,7 @@
}
// get current GD
- Win32GraphicsDevice oldDev = (Win32GraphicsDevice)winGraphicsConfig
- .getDevice();
+ Win32GraphicsDevice oldDev = winGraphicsConfig.getDevice();
Win32GraphicsDevice newDev;
GraphicsDevice devs[] = GraphicsEnvironment
--- a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceData.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceData.java Tue Nov 17 13:09:16 2015 -0800
@@ -63,9 +63,12 @@
import static sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType.*;
import sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType;
import java.awt.BufferCapabilities.FlipContents;
+import java.awt.Dimension;
import java.awt.Window;
+import java.awt.geom.AffineTransform;
import sun.awt.SunToolkit;
import sun.awt.image.SunVolatileImage;
+import sun.awt.windows.WWindowPeer;
import sun.java2d.ScreenUpdateManager;
import sun.java2d.StateTracker;
import sun.java2d.SurfaceDataProxy;
@@ -162,6 +165,8 @@
private int type;
private int width, height;
+ private final double scaleX;
+ private final double scaleY;
// these fields are set from the native code when the surface is
// initialized
private int nativeWidth, nativeHeight;
@@ -218,16 +223,29 @@
{
super(getCustomSurfaceType(type), cm);
this.graphicsDevice = gc.getD3DDevice();
+ this.scaleX = type == TEXTURE ? 1 : graphicsDevice.getDefaultScaleX();
+ this.scaleY = type == TEXTURE ? 1 : graphicsDevice.getDefaultScaleY();
this.peer = peer;
this.type = type;
- this.width = width;
- this.height = height;
+
+ if (scaleX == 1 && scaleY == 1) {
+ this.width = width;
+ this.height = height;
+ } else if (peer instanceof WWindowPeer) {
+ Dimension scaledSize = ((WWindowPeer) peer).getScaledWindowSize();
+ this.width = scaledSize.width;
+ this.height = scaledSize.height;
+ } else {
+ this.width = (int) Math.ceil(width * scaleX);
+ this.height = (int) Math.ceil(height * scaleY);
+ }
+
this.offscreenImage = image;
this.backBuffersNum = numBackBuffers;
this.swapEffect = swapEffect;
this.syncType = vSyncType;
- initOps(graphicsDevice.getScreen(), width, height);
+ initOps(graphicsDevice.getScreen(), this.width, this.height);
if (type == WINDOW) {
// we put the surface into the "lost"
// state; it will be restored by the D3DScreenUpdateManager
@@ -241,6 +259,16 @@
}
@Override
+ public double getDefaultScaleX() {
+ return scaleX;
+ }
+
+ @Override
+ public double getDefaultScaleY() {
+ return scaleY;
+ }
+
+ @Override
public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
return D3DSurfaceDataProxy.
createProxy(srcData,
@@ -777,8 +805,12 @@
public Rectangle getBounds() {
if (type == FLIP_BACKBUFFER || type == WINDOW) {
+ double scaleX = getDefaultScaleX();
+ double scaleY = getDefaultScaleY();
Rectangle r = peer.getBounds();
r.x = r.y = 0;
+ r.width = (int) Math.ceil(r.width * scaleX);
+ r.height = (int) Math.ceil(r.height * scaleY);
return r;
} else {
return new Rectangle(width, height);
--- a/jdk/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java Tue Nov 17 13:09:16 2015 -0800
@@ -31,8 +31,10 @@
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
import java.awt.image.ColorModel;
import sun.awt.SunToolkit;
+import sun.awt.Win32GraphicsDevice;
import sun.awt.windows.WComponentPeer;
import sun.java2d.SurfaceData;
@@ -40,6 +42,8 @@
protected WComponentPeer peer;
private WGLGraphicsConfig graphicsConfig;
+ protected double scaleX = 1;
+ protected double scaleY = 1;
private native void initOps(long pConfigInfo, WComponentPeer peer,
long hwnd);
@@ -50,6 +54,9 @@
super(gc, cm, type);
this.peer = peer;
this.graphicsConfig = gc;
+ Win32GraphicsDevice device = gc.getDevice();
+ this.scaleX = type == TEXTURE ? 1 : device.getDefaultScaleX();
+ this.scaleY = type == TEXTURE ? 1 : device.getDefaultScaleY();
long pConfigInfo = gc.getNativeConfigInfo();
long hwnd = peer != null ? peer.getHWnd() : 0L;
@@ -57,6 +64,16 @@
initOps(pConfigInfo, peer, hwnd);
}
+ @Override
+ public double getDefaultScaleX() {
+ return scaleX;
+ }
+
+ @Override
+ public double getDefaultScaleY() {
+ return scaleY;
+ }
+
public GraphicsConfiguration getDeviceConfiguration() {
return graphicsConfig;
}
@@ -148,6 +165,8 @@
public Rectangle getBounds() {
Rectangle r = peer.getBounds();
r.x = r.y = 0;
+ r.width = (int) Math.ceil(r.width * scaleX);
+ r.height = (int) Math.ceil(r.height * scaleY);
return r;
}
@@ -208,11 +227,11 @@
{
super(peer, gc, cm, type);
- this.width = width;
- this.height = height;
+ this.width = (int) Math.ceil(width * scaleX);
+ this.height = (int) Math.ceil(height * scaleY);
offscreenImage = image;
- initSurface(width, height);
+ initSurface(this.width, this.height);
}
public SurfaceData getReplacement() {
@@ -222,6 +241,8 @@
public Rectangle getBounds() {
if (type == FLIP_BACKBUFFER) {
Rectangle r = peer.getBounds();
+ r.width = (int) Math.ceil(r.width * scaleX);
+ r.height = (int) Math.ceil(r.height * scaleY);
r.x = r.y = 0;
return r;
} else {
--- a/jdk/src/java.desktop/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java Tue Nov 17 13:09:16 2015 -0800
@@ -28,6 +28,7 @@
import java.awt.Rectangle;
import java.awt.GraphicsConfiguration;
import java.awt.color.ColorSpace;
+import java.awt.geom.AffineTransform;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DirectColorModel;
@@ -77,6 +78,9 @@
private static native void initIDs(Class<?> xorComp);
+ private final double scaleX;
+ private final double scaleY;
+
static {
initIDs(XORComposite.class);
if (WindowsFlags.isGdiBlitEnabled()) {
@@ -265,13 +269,23 @@
this.graphicsConfig =
(Win32GraphicsConfig) peer.getGraphicsConfiguration();
this.solidloops = graphicsConfig.getSolidLoops(sType);
-
- Win32GraphicsDevice gd =
- (Win32GraphicsDevice)graphicsConfig.getDevice();
+ Win32GraphicsDevice gd = graphicsConfig.getDevice();
+ scaleX = gd.getDefaultScaleX();
+ scaleY = gd.getDefaultScaleY();
initOps(peer, depth, rMask, gMask, bMask, gd.getScreen());
setBlitProxyKey(graphicsConfig.getProxyKey());
}
+ @Override
+ public double getDefaultScaleX() {
+ return scaleX;
+ }
+
+ @Override
+ public double getDefaultScaleY() {
+ return scaleY;
+ }
+
/**
* {@inheritDoc}
*
@@ -288,6 +302,8 @@
public Rectangle getBounds() {
Rectangle r = peer.getBounds();
r.x = r.y = 0;
+ r.width = (int) Math.ceil(r.width * scaleX);
+ r.height = (int) Math.ceil(r.height * scaleY);
return r;
}
--- a/jdk/src/java.desktop/windows/native/libawt/windows/MouseInfo.cpp Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/MouseInfo.cpp Tue Nov 17 13:09:16 2015 -0800
@@ -94,12 +94,21 @@
pointClass = (jclass)env->NewGlobalRef(pointClassLocal);
env->DeleteLocalRef(pointClassLocal);
}
+
+ int screen = AwtWin32GraphicsDevice::GetDefaultDeviceIndex();
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
+
xID = env->GetFieldID(pointClass, "x", "I");
CHECK_NULL_RETURN(xID, (jint)0);
yID = env->GetFieldID(pointClass, "y", "I");
CHECK_NULL_RETURN(yID, (jint)0);
- env->SetIntField(point, xID, pt.x);
- env->SetIntField(point, yID, pt.y);
+
+ int x = (device == NULL) ? pt.x : device->ScaleDownX(pt.x);
+ int y = (device == NULL) ? pt.y : device->ScaleDownY(pt.y);
+
+ env->SetIntField(point, xID, x);
+ env->SetIntField(point, yID, y);
// Always return 0 on Windows: we assume there's always a
// virtual screen device used.
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Choice.cpp Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Choice.cpp Tue Nov 17 13:09:16 2015 -0800
@@ -206,9 +206,10 @@
int itemHeight =(int)::SendMessage(GetHWnd(), CB_GETITEMHEIGHT, (UINT)0,0);
int numItemsToShow = (int)::SendMessage(GetHWnd(), CB_GETCOUNT, 0,0);
numItemsToShow = min(MINIMUM_NUMBER_OF_VISIBLE_ITEMS, numItemsToShow);
+
// drop-down height snaps to nearest line, so add a
// fudge factor of 1/2 line to ensure last line shows
- return itemHeight*numItemsToShow + itemHeight/2;
+ return ScaleDownY(itemHeight * numItemsToShow + itemHeight / 2);
}
// get the height of the field portion of the combobox
@@ -221,7 +222,7 @@
// Win 4.x (3d edge) vs 3.x (1 pixel line)
borderHeight = ::GetSystemMetrics(SM_CYEDGE);
fieldHeight += borderHeight*2;
- return fieldHeight;
+ return ScaleDownY(fieldHeight);
}
// gets the total height of the combobox, including drop down
@@ -325,8 +326,8 @@
* Fix: Set the Choice to its actual size in the component.
*/
::GetClientRect(GetHWnd(), &rc);
- env->SetIntField(target, AwtComponent::widthID, (jint)rc.right);
- env->SetIntField(target, AwtComponent::heightID, (jint)rc.bottom);
+ env->SetIntField(target, AwtComponent::widthID, ScaleDownX(rc.right));
+ env->SetIntField(target, AwtComponent::heightID, ScaleDownY(rc.bottom));
env->DeleteLocalRef(target);
env->DeleteLocalRef(parent);
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp Tue Nov 17 13:09:16 2015 -0800
@@ -963,6 +963,12 @@
::MapWindowPoints(HWND_DESKTOP, ::GetParent(GetHWnd()), (LPPOINT)&rc, 2);
DTRACE_PRINTLN4("AwtComponent::Reshape from %d, %d, %d, %d", rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top);
#endif
+
+ x = ScaleUpX(x);
+ y = ScaleUpY(y);
+ w = ScaleUpX(w);
+ h = ScaleUpY(h);
+
AwtWindow* container = GetContainer();
AwtComponent* parent = GetParent();
if (container != NULL && container == parent) {
@@ -2212,8 +2218,11 @@
}
for(i = 0; i < 2; i++) {
if (un[i] != 0) {
- DoCallback("handleExpose", "(IIII)V", un[i]->left, un[i]->top,
- un[i]->right-un[i]->left, un[i]->bottom-un[i]->top);
+ DoCallback("handleExpose", "(IIII)V",
+ ScaleDownX(un[i]->left),
+ ScaleDownY(un[i]->top),
+ ScaleDownX(un[i]->right - un[i]->left),
+ ScaleDownY(un[i]->bottom - un[i]->top));
}
}
delete [] buffer;
@@ -4608,6 +4617,34 @@
}
}
+int AwtComponent::ScaleUpX(int x) {
+ int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
+ return device == NULL ? x : device->ScaleUpX(x);
+}
+
+int AwtComponent::ScaleUpY(int y) {
+ int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
+ return device == NULL ? y : device->ScaleUpY(y);
+}
+
+int AwtComponent::ScaleDownX(int x) {
+ int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
+ return device == NULL ? x : device->ScaleDownX(x);
+}
+
+int AwtComponent::ScaleDownY(int y) {
+ int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
+ return device == NULL ? y : device->ScaleDownY(y);
+}
+
jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
@@ -4901,8 +4938,9 @@
jobject mouseEvent = env->NewObject(mouseEventCls, mouseEventConst,
target,
id, when, modifiers,
- x+insets.left, y+insets.top,
- xAbs, yAbs,
+ ScaleDownX(x + insets.left),
+ ScaleDownY(y + insets.top),
+ ScaleDownX(xAbs), ScaleDownY(yAbs),
clickCount, popupTrigger, button);
if (safe_ExceptionOccurred(env)) {
@@ -4969,8 +5007,10 @@
mouseWheelEventConst,
target,
id, when, modifiers,
- x+insets.left, y+insets.top,
- xAbs, yAbs,
+ ScaleDownX(x + insets.left),
+ ScaleDownY(y + insets.top),
+ ScaleDownX(xAbs),
+ ScaleDownY(yAbs),
clickCount, popupTrigger,
scrollType, scrollAmount,
roundedWheelRotation, preciseWheelRotation);
@@ -5476,7 +5516,8 @@
RECT rect;
VERIFY(::GetWindowRect(p->GetHWnd(),&rect));
result = JNU_NewObjectByName(env, "java/awt/Point", "(II)V",
- rect.left, rect.top);
+ p->ScaleDownX(rect.left),
+ p->ScaleDownY(rect.top));
}
ret:
env->DeleteGlobalRef(self);
@@ -7064,6 +7105,11 @@
target = parent;
}
+ x = ScaleUpX(x);
+ y = ScaleUpY(y);
+ width = ScaleUpX(width);
+ height = ScaleUpY(height);
+
// Test whether component's bounds match the native window's
RECT rect;
VERIFY(::GetWindowRect(GetHWnd(), &rect));
@@ -7256,5 +7302,4 @@
removedDCs = removedDCs->next;
delete tmpDCList;
}
-}
-
+}
\ No newline at end of file
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h Tue Nov 17 13:09:16 2015 -0800
@@ -746,6 +746,11 @@
virtual void FillBackground(HDC hMemoryDC, SIZE &size);
virtual void FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha);
+ int ScaleUpX(int x);
+ int ScaleUpY(int y);
+ int ScaleDownX(int x);
+ int ScaleDownY(int y);
+
private:
/* A bitmask keeps the button's numbers as MK_LBUTTON, MK_MBUTTON, MK_RBUTTON
* which are allowed to
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp Tue Nov 17 13:09:16 2015 -0800
@@ -398,6 +398,38 @@
}
+static int ScaleUpX(float x) {
+ int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
+ ::GetDesktopWindow());
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
+ return device == NULL ? x : device->ScaleUpX(x);
+}
+
+static int ScaleUpY(int y) {
+ int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
+ ::GetDesktopWindow());
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
+ return device == NULL ? y : device->ScaleUpY(y);
+}
+
+static int ScaleDownX(int x) {
+ int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
+ ::GetDesktopWindow());
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
+ return device == NULL ? x : device->ScaleDownX(x);
+}
+
+static int ScaleDownY(int y) {
+ int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
+ ::GetDesktopWindow());
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
+ return device == NULL ? y : device->ScaleDownY(y);
+}
+
static HFONT CreateHFont_sub(LPCWSTR name, int style, int height,
int angle=0, float awScale=1.0f)
{
@@ -424,7 +456,7 @@
logFont.lfUnderline = 0;//(style & java_awt_Font_UNDERLINE) != 0;
// Get point size
- logFont.lfHeight = -height;
+ logFont.lfHeight = ScaleUpY(-height);
// Set font name
WCHAR tmpname[80];
@@ -451,7 +483,7 @@
VERIFY(::DeleteObject(oldFont));
}
avgWidth = tm.tmAveCharWidth;
- logFont.lfWidth = (LONG)((fabs)(avgWidth*awScale));
+ logFont.lfWidth = (LONG) ScaleUpX((fabs) (avgWidth * awScale));
hFont = ::CreateFontIndirect(&logFont);
DASSERT(hFont != NULL);
VERIFY(::ReleaseDC(0, hDC));
@@ -535,19 +567,20 @@
int ascent = metrics.tmAscent;
int descent = metrics.tmDescent;
int leading = metrics.tmExternalLeading;
- env->SetIntField(fontMetrics, AwtFont::ascentID, ascent);
- env->SetIntField(fontMetrics, AwtFont::descentID, descent);
- env->SetIntField(fontMetrics, AwtFont::leadingID, leading);
- env->SetIntField(fontMetrics, AwtFont::heightID, metrics.tmAscent +
- metrics.tmDescent + leading);
- env->SetIntField(fontMetrics, AwtFont::maxAscentID, ascent);
- env->SetIntField(fontMetrics, AwtFont::maxDescentID, descent);
+
+ env->SetIntField(fontMetrics, AwtFont::ascentID, ScaleDownY(ascent));
+ env->SetIntField(fontMetrics, AwtFont::descentID, ScaleDownY(descent));
+ env->SetIntField(fontMetrics, AwtFont::leadingID, ScaleDownX(leading));
+ env->SetIntField(fontMetrics, AwtFont::heightID,
+ ScaleDownY(metrics.tmAscent + metrics.tmDescent + leading));
+ env->SetIntField(fontMetrics, AwtFont::maxAscentID, ScaleDownY(ascent));
+ env->SetIntField(fontMetrics, AwtFont::maxDescentID, ScaleDownY(descent));
int maxHeight = ascent + descent + leading;
- env->SetIntField(fontMetrics, AwtFont::maxHeightID, maxHeight);
+ env->SetIntField(fontMetrics, AwtFont::maxHeightID, ScaleDownY(maxHeight));
int maxAdvance = metrics.tmMaxCharWidth;
- env->SetIntField(fontMetrics, AwtFont::maxAdvanceID, maxAdvance);
+ env->SetIntField(fontMetrics, AwtFont::maxAdvanceID, ScaleDownX(maxAdvance));
awtFont->m_overhang = metrics.tmOverhang;
@@ -818,6 +851,7 @@
jobject font = env->GetObjectField(self, AwtFont::fontID);
long ret = AwtFont::getMFStringWidth(hDC, font, str);
+ ret = ScaleDownX(ret);
VERIFY(::ReleaseDC(0, hDC));
return ret;
@@ -924,7 +958,7 @@
}
env->ReleasePrimitiveArrayCritical(str, pStrBody, 0);
- return result;
+ return ScaleDownX(result);
CATCH_BAD_ALLOC_RET(0);
}
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp Tue Nov 17 13:09:16 2015 -0800
@@ -80,6 +80,13 @@
(PVOID)newSpeed,
SPIF_SENDCHANGE);
+ int primaryIndex = AwtWin32GraphicsDevice::GetDefaultDeviceIndex();
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice *device = devices->GetDevice(primaryIndex);
+
+ x = (device == NULL) ? x : device->ScaleUpX(x);
+ y = (device == NULL) ? y : device->ScaleUpY(y);
+
POINT curPos;
::GetCursorPos(&curPos);
x -= curPos.x;
@@ -217,11 +224,24 @@
AwtWin32GraphicsDevice::SelectPalette(hdcMem, primaryIndex);
AwtWin32GraphicsDevice::RealizePalette(hdcMem, primaryIndex);
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice *device = devices->GetDevice(primaryIndex);
+ int sWidth = (device == NULL) ? width : device->ScaleUpX(width);
+ int sHeight = (device == NULL) ? height : device->ScaleUpY(height);
+
// copy screen image to offscreen bitmap
// CAPTUREBLT flag is required to capture WS_EX_LAYERED windows' contents
// correctly on Win2K/XP
- VERIFY(::BitBlt(hdcMem, 0, 0, width, height, hdcScreen, x, y,
- SRCCOPY|CAPTUREBLT) != 0);
+ if (width == sWidth && height == sHeight) {
+ VERIFY(::BitBlt(hdcMem, 0, 0, width, height, hdcScreen, x, y,
+ SRCCOPY | CAPTUREBLT) != 0);
+ } else {
+ int sX = (device == NULL) ? x : device->ScaleUpX(x);
+ int sY = (device == NULL) ? y : device->ScaleUpY(y);
+ VERIFY(::StretchBlt(hdcMem, 0, 0, width, height,
+ hdcScreen, sX, sY, sWidth, sHeight,
+ SRCCOPY | CAPTUREBLT) != 0);
+ }
static const int BITS_PER_PIXEL = 32;
static const int BYTES_PER_PIXEL = BITS_PER_PIXEL/8;
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp Tue Nov 17 13:09:16 2015 -0800
@@ -2355,8 +2355,13 @@
{
TRY;
- return ::GetSystemMetrics(SM_CXSCREEN);
-
+ int width = ::GetSystemMetrics(SM_CXSCREEN);
+
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice *device = devices->GetDevice(
+ AwtWin32GraphicsDevice::GetDefaultDeviceIndex());
+
+ return (device == NULL) ? width : device->ScaleDownX(width);
CATCH_BAD_ALLOC_RET(0);
}
@@ -2370,7 +2375,12 @@
{
TRY;
- return ::GetSystemMetrics(SM_CYSCREEN);
+ int height = ::GetSystemMetrics(SM_CYSCREEN);
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice *device = devices->GetDevice(
+ AwtWin32GraphicsDevice::GetDefaultDeviceIndex());
+
+ return (device == NULL) ? height : device->ScaleDownY(height);
CATCH_BAD_ALLOC_RET(0);
}
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsConfig.cpp Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsConfig.cpp Tue Nov 17 13:09:16 2015 -0800
@@ -95,19 +95,31 @@
mid = env->GetMethodID(clazz, "<init>", "(IIII)V");
if (mid != 0) {
RECT rRW = {0, 0, 0, 0};
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
+
if (TRUE == MonitorBounds(AwtWin32GraphicsDevice::GetMonitor(screen), &rRW)) {
- bounds = env->NewObject(clazz, mid,
- rRW.left, rRW.top,
- rRW.right - rRW.left,
- rRW.bottom - rRW.top);
+
+ int x = (device == NULL) ? rRW.left : device->ScaleDownX(rRW.left);
+ int y = (device == NULL) ? rRW.top : device->ScaleDownY(rRW.top);
+ int w = (device == NULL) ? rRW.right - rRW.left
+ : device->ScaleDownX(rRW.right - rRW.left);
+ int h = (device == NULL) ? rRW.bottom - rRW.top
+ : device->ScaleDownY(rRW.bottom - rRW.top);
+
+ bounds = env->NewObject(clazz, mid, x, y, w, h);
+
}
else {
// 4910760 - don't return a null bounds, return the bounds of the
// primary screen
+ int w = ::GetSystemMetrics(SM_CXSCREEN);
+ int h = ::GetSystemMetrics(SM_CYSCREEN);
+
bounds = env->NewObject(clazz, mid,
0, 0,
- ::GetSystemMetrics(SM_CXSCREEN),
- ::GetSystemMetrics(SM_CYSCREEN));
+ device == NULL ? w : device->ScaleDownX(w),
+ device == NULL ? h : device->ScaleDownY(h));
}
if (safe_ExceptionOccurred(env)) {
return 0;
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp Tue Nov 17 13:09:16 2015 -0800
@@ -49,6 +49,12 @@
#include "dither.h"
#include "img_util_md.h"
#include "Devices.h"
+#include <d2d1.h>
+#pragma comment(lib, "d2d1")
+
+#ifndef MDT_Effective_DPI
+#define MDT_Effective_DPI 0
+#endif
uns_ordered_dither_array img_oda_alpha;
@@ -74,6 +80,8 @@
{
this->screen = screen;
this->devicesArray = arr;
+ this->scaleX = 1;
+ this->scaleY = 1;
javaDevice = NULL;
colorData = new ImgColorData;
colorData->grayscale = GS_NOTGRAY;
@@ -617,6 +625,104 @@
}
/**
+ * Sets horizontal and vertical scale factors
+ */
+void AwtWin32GraphicsDevice::SetScale(float sx, float sy)
+{
+ scaleX = sx;
+ scaleY = sy;
+}
+
+int AwtWin32GraphicsDevice::ScaleUpX(int x)
+{
+ return (int)ceil(x * scaleX);
+}
+
+int AwtWin32GraphicsDevice::ScaleUpY(int y)
+{
+ return (int)ceil(y * scaleY);
+}
+
+int AwtWin32GraphicsDevice::ScaleDownX(int x)
+{
+ return (int)ceil(x / scaleX);
+}
+
+int AwtWin32GraphicsDevice::ScaleDownY(int y)
+{
+ return (int)ceil(y / scaleY);
+}
+
+void AwtWin32GraphicsDevice::InitDesktopScales()
+{
+ unsigned x = 0;
+ unsigned y = 0;
+ float dpiX = -1.0f;
+ float dpiY = -1.0f;
+
+ // for debug purposes
+ static float scale = -2.0f;
+ if (scale == -2) {
+ scale = -1;
+ char *uiScale = getenv("J2D_UISCALE");
+ if (uiScale != NULL) {
+ scale = (float)strtod(uiScale, NULL);
+ if (errno == ERANGE || scale <= 0) {
+ scale = -1;
+ }
+ }
+ }
+
+ if (scale > 0) {
+ SetScale(scale, scale);
+ return;
+ }
+
+ typedef HRESULT(WINAPI GetDpiForMonitorFunc)(HMONITOR, int, UINT*, UINT*);
+ static HMODULE hLibSHCoreDll = NULL;
+ static GetDpiForMonitorFunc *lpGetDpiForMonitor = NULL;
+
+ if (hLibSHCoreDll == NULL) {
+ hLibSHCoreDll = JDK_LoadSystemLibrary("shcore.dll");
+ if (hLibSHCoreDll != NULL) {
+ lpGetDpiForMonitor = (GetDpiForMonitorFunc*)GetProcAddress(
+ hLibSHCoreDll, "GetDpiForMonitor");
+ }
+ }
+
+ if (lpGetDpiForMonitor != NULL) {
+ HRESULT hResult = lpGetDpiForMonitor(GetMonitor(),
+ MDT_Effective_DPI, &x, &y);
+ if (hResult == S_OK) {
+ dpiX = static_cast<float>(x);
+ dpiY = static_cast<float>(y);
+ }
+ } else {
+ ID2D1Factory* m_pDirect2dFactory;
+ HRESULT res = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
+ &m_pDirect2dFactory);
+ if (res == S_OK) {
+ m_pDirect2dFactory->GetDesktopDpi(&dpiX, &dpiY);
+ m_pDirect2dFactory->Release();
+ }
+ }
+
+ if (dpiX > 0 && dpiY > 0) {
+ SetScale(dpiX / 96, dpiY / 96);
+ }
+}
+
+float AwtWin32GraphicsDevice::GetScaleX()
+{
+ return scaleX;
+}
+
+float AwtWin32GraphicsDevice::GetScaleY()
+{
+ return scaleY;
+}
+
+/**
* Disables offscreen acceleration for this device. This
* sets a flag in the java object that is used to determine
* whether offscreen surfaces can be created on the device.
@@ -1304,3 +1410,65 @@
Devices::InstanceAccess devices;
devices->GetDevice(screen)->SetJavaDevice(env, thisPtr);
}
+
+/*
+ * Class: sun_awt_Win32GraphicsDevice
+ * Method: setNativeScale
+ * Signature: (I,F,F)V
+ */
+JNIEXPORT void JNICALL
+ Java_sun_awt_Win32GraphicsDevice_setNativeScale
+ (JNIEnv *env, jobject thisPtr, jint screen, jfloat scaleX, jfloat scaleY)
+{
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
+
+ if (device != NULL ) {
+ device->SetScale(scaleX, scaleY);
+ }
+}
+
+/*
+ * Class: sun_awt_Win32GraphicsDevice
+ * Method: getNativeScaleX
+ * Signature: (I)F
+ */
+JNIEXPORT jfloat JNICALL
+ Java_sun_awt_Win32GraphicsDevice_getNativeScaleX
+ (JNIEnv *env, jobject thisPtr, jint screen)
+{
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
+ return (device == NULL) ? 1 : device->GetScaleX();
+}
+
+/*
+ * Class: sun_awt_Win32GraphicsDevice
+ * Method: getNativeScaleY
+ * Signature: (I)F
+ */
+JNIEXPORT jfloat JNICALL
+ Java_sun_awt_Win32GraphicsDevice_getNativeScaleY
+ (JNIEnv *env, jobject thisPtr, jint screen)
+{
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
+ return (device == NULL) ? 1 : device->GetScaleY();
+}
+
+/*
+* Class: sun_awt_Win32GraphicsDevice
+* Method: initNativeScale
+* Signature: (I)V;
+*/
+JNIEXPORT void JNICALL
+Java_sun_awt_Win32GraphicsDevice_initNativeScale
+(JNIEnv *env, jobject thisPtr, jint screen)
+{
+ Devices::InstanceAccess devices;
+ AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
+
+ if (device != NULL) {
+ device->InitDesktopScales();
+ }
+}
\ No newline at end of file
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.h Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.h Tue Nov 17 13:09:16 2015 -0800
@@ -66,6 +66,14 @@
void Release();
void DisableOffscreenAcceleration();
void Invalidate(JNIEnv *env);
+ void InitDesktopScales();
+ void SetScale(float scaleX, float scaleY);
+ float GetScaleX();
+ float GetScaleY();
+ int ScaleUpX(int x);
+ int ScaleUpY(int y);
+ int ScaleDownX(int x);
+ int ScaleDownY(int y);
static int DeviceIndexForWindow(HWND hWnd);
static jobject GetColorModel(JNIEnv *env, jboolean dynamic,
@@ -107,6 +115,8 @@
LPMONITORINFO pMonitorInfo;
jobject javaDevice;
Devices *devicesArray;
+ float scaleX;
+ float scaleY;
static HDC MakeDCFromMonitor(HMONITOR);
};
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp Tue Nov 17 13:09:16 2015 -0800
@@ -1407,19 +1407,19 @@
/* Get insets into our peer directly */
jobject peerInsets = (env)->GetObjectField(peer, AwtPanel::insets_ID);
DASSERT(!safe_ExceptionOccurred(env));
+
if (peerInsets != NULL) { // may have been called during creation
- (env)->SetIntField(peerInsets, AwtInsets::topID, m_insets.top);
- (env)->SetIntField(peerInsets, AwtInsets::bottomID,
- m_insets.bottom);
- (env)->SetIntField(peerInsets, AwtInsets::leftID, m_insets.left);
- (env)->SetIntField(peerInsets, AwtInsets::rightID, m_insets.right);
+ (env)->SetIntField(peerInsets, AwtInsets::topID, ScaleDownY(m_insets.top));
+ (env)->SetIntField(peerInsets, AwtInsets::bottomID, ScaleDownY(m_insets.bottom));
+ (env)->SetIntField(peerInsets, AwtInsets::leftID, ScaleDownX(m_insets.left));
+ (env)->SetIntField(peerInsets, AwtInsets::rightID, ScaleDownX(m_insets.right));
}
/* Get insets into the Inset object (if any) that was passed */
if (insets != NULL) {
- (env)->SetIntField(insets, AwtInsets::topID, m_insets.top);
- (env)->SetIntField(insets, AwtInsets::bottomID, m_insets.bottom);
- (env)->SetIntField(insets, AwtInsets::leftID, m_insets.left);
- (env)->SetIntField(insets, AwtInsets::rightID, m_insets.right);
+ (env)->SetIntField(insets, AwtInsets::topID, ScaleDownY(m_insets.top));
+ (env)->SetIntField(insets, AwtInsets::bottomID, ScaleDownY(m_insets.bottom));
+ (env)->SetIntField(insets, AwtInsets::leftID, ScaleDownX(m_insets.left));
+ (env)->SetIntField(insets, AwtInsets::rightID, ScaleDownX(m_insets.right));
}
env->DeleteLocalRef(peerInsets);
@@ -1735,10 +1735,10 @@
RECT rect;
::GetWindowRect(GetHWnd(), &rect);
- (env)->SetIntField(target, AwtComponent::xID, rect.left);
- (env)->SetIntField(target, AwtComponent::yID, rect.top);
- (env)->SetIntField(peer, AwtWindow::sysXID, rect.left);
- (env)->SetIntField(peer, AwtWindow::sysYID, rect.top);
+ (env)->SetIntField(target, AwtComponent::xID, ScaleDownX(rect.left));
+ (env)->SetIntField(target, AwtComponent::yID, ScaleDownY(rect.top));
+ (env)->SetIntField(peer, AwtWindow::sysXID, ScaleDownX(rect.left));
+ (env)->SetIntField(peer, AwtWindow::sysYID, ScaleDownY(rect.top));
SendComponentEvent(java_awt_event_ComponentEvent_COMPONENT_MOVED);
env->DeleteLocalRef(target);
@@ -1803,12 +1803,12 @@
int newWidth = w + m_insets.left + m_insets.right;
int newHeight = h + m_insets.top + m_insets.bottom;
- (env)->SetIntField(target, AwtComponent::widthID, newWidth);
- (env)->SetIntField(target, AwtComponent::heightID, newHeight);
+ (env)->SetIntField(target, AwtComponent::widthID, ScaleDownX(newWidth));
+ (env)->SetIntField(target, AwtComponent::heightID, ScaleDownY(newHeight));
jobject peer = GetPeer(env);
- (env)->SetIntField(peer, AwtWindow::sysWID, newWidth);
- (env)->SetIntField(peer, AwtWindow::sysHID, newHeight);
+ (env)->SetIntField(peer, AwtWindow::sysWID, ScaleDownX(newWidth));
+ (env)->SetIntField(peer, AwtWindow::sysHID, ScaleDownY(newHeight));
if (!AwtWindow::IsResizing()) {
WindowResized();
@@ -3072,6 +3072,25 @@
delete data;
}
+void AwtWindow::_GetNativeWindowSize(void* param) {
+
+ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+
+ SizeStruct *ss = (SizeStruct *)param;
+ jobject self = ss->window;
+ AwtWindow *window = NULL;
+ PDATA pData;
+ JNI_CHECK_PEER_RETURN(self);
+ window = (AwtWindow *)pData;
+
+ RECT rc;
+ ::GetWindowRect(window->GetHWnd(), &rc);
+ ss->w = rc.right - rc.left;
+ ss->h = rc.bottom - rc.top;
+
+ env->DeleteGlobalRef(self);
+}
+
extern "C" {
/*
@@ -3303,6 +3322,46 @@
/*
* Class: sun_awt_windows_WWindowPeer
+* Method: getNativeWindowSize
+* Signature: ()Ljava/awt/Dimension;
+*/
+JNIEXPORT jobject JNICALL Java_sun_awt_windows_WWindowPeer_getNativeWindowSize
+(JNIEnv *env, jobject self) {
+
+ jobject res = NULL;
+ TRY;
+ SizeStruct *ss = new SizeStruct;
+ ss->window = env->NewGlobalRef(self);
+
+ AwtToolkit::GetInstance().SyncCall(AwtWindow::_GetNativeWindowSize, ss);
+
+ int w = ss->w;
+ int h = ss->h;
+
+ delete ss;
+ // global ref is deleted in _GetNativeWindowSize()
+
+ static jmethodID dimMID = NULL;
+ static jclass dimClassID = NULL;
+ if (dimClassID == NULL) {
+ jclass dimClassIDLocal = env->FindClass("java/awt/Dimension");
+ CHECK_NULL_RETURN(dimClassIDLocal, NULL);
+ dimClassID = (jclass)env->NewGlobalRef(dimClassIDLocal);
+ env->DeleteLocalRef(dimClassIDLocal);
+ }
+
+ if (dimMID == NULL) {
+ dimMID = env->GetMethodID(dimClassID, "<init>", "(II)V");
+ CHECK_NULL_RETURN(dimMID, NULL);
+ }
+
+ return env->NewObject(dimClassID, dimMID, w, h);
+
+ CATCH_BAD_ALLOC_RET(NULL);
+}
+
+/*
+ * Class: sun_awt_windows_WWindowPeer
* Method: getSysMinWidth
* Signature: ()I
*/
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Window.h Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Window.h Tue Nov 17 13:09:16 2015 -0800
@@ -241,6 +241,7 @@
static void _UpdateWindow(void* param);
static void _RepositionSecurityWarning(void* param);
static void _SetFullScreenExclusiveModeState(void* param);
+ static void _GetNativeWindowSize(void* param);
inline static BOOL IsResizing() {
return sm_resizing;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Robot/HiDPIMouseClick/HiDPIRobotMouseClick.java Tue Nov 17 13:09:16 2015 -0800
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015, 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 java.awt.Frame;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import javax.swing.UIManager;
+
+/* @test
+ * @bug 8073320
+ * @summary Windows HiDPI support
+ * @author Alexander Scherbatiy
+ * @requires (os.family == "windows")
+ * @run main/othervm -Dsun.java2d.win.uiScale=2 HiDPIRobotMouseClick
+ */
+public class HiDPIRobotMouseClick {
+
+ private static volatile int mouseX;
+ private static volatile int mouseY;
+
+ public static void main(String[] args) throws Exception {
+
+ try {
+ UIManager.setLookAndFeel(
+ "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
+ } catch (Exception e) {
+ return;
+ }
+
+ Frame frame = new Frame();
+ frame.setBounds(30, 20, 400, 300);
+ frame.setUndecorated(true);
+
+ frame.addMouseListener(new MouseAdapter() {
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ mouseX = e.getXOnScreen();
+ mouseY = e.getYOnScreen();
+ }
+ });
+
+ frame.setVisible(true);
+
+ Robot robot = new Robot();
+ robot.waitForIdle();
+ Thread.sleep(200);
+
+ Rectangle rect = frame.getBounds();
+ rect.setLocation(frame.getLocationOnScreen());
+
+ int x = (int) rect.getCenterX();
+ int y = (int) rect.getCenterY();
+
+ robot.mouseMove(x, y);
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ robot.waitForIdle();
+
+ if (x != mouseX || y != mouseY) {
+ throw new RuntimeException("Wrong mouse click point!");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Robot/HiDPIScreenCapture/HiDPIRobotScreenCaptureTest.java Tue Nov 17 13:09:16 2015 -0800
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015, 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 java.awt.BorderLayout;
+import java.awt.Canvas;
+import java.awt.Color;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Panel;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.image.BufferedImage;
+import javax.swing.UIManager;
+
+/* @test
+ * @bug 8073320
+ * @summary Windows HiDPI support
+ * @author Alexander Scherbatiy
+ * @requires (os.family == "windows")
+ * @run main/othervm -Dsun.java2d.win.uiScaleX=3 -Dsun.java2d.win.uiScaleY=2
+ * HiDPIRobotScreenCaptureTest
+ */
+public class HiDPIRobotScreenCaptureTest {
+
+ private static final Color[] COLORS = {
+ Color.GREEN, Color.BLUE, Color.ORANGE, Color.RED};
+
+ public static void main(String[] args) throws Exception {
+
+ try {
+ UIManager.setLookAndFeel(
+ "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
+ } catch (Exception e) {
+ return;
+ }
+
+ Frame frame = new Frame();
+ frame.setBounds(40, 30, 400, 300);
+ frame.setUndecorated(true);
+
+ Panel panel = new Panel(new BorderLayout());
+ Canvas canvas = new Canvas() {
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+ int w = getWidth();
+ int h = getHeight();
+ g.setColor(COLORS[0]);
+ g.fillRect(0, 0, w / 2, h / 2);
+ g.setColor(COLORS[1]);
+ g.fillRect(w / 2, 0, w / 2, h / 2);
+ g.setColor(COLORS[2]);
+ g.fillRect(0, h / 2, w / 2, h / 2);
+ g.setColor(COLORS[3]);
+ g.fillRect(w / 2, h / 2, w / 2, h / 2);
+ }
+ };
+
+ panel.add(canvas);
+ frame.add(panel);
+ frame.setVisible(true);
+ Robot robot = new Robot();
+ robot.waitForIdle();
+ Thread.sleep(200);
+
+ Rectangle rect = canvas.getBounds();
+ rect.setLocation(canvas.getLocationOnScreen());
+
+ BufferedImage image = robot.createScreenCapture(rect);
+ frame.dispose();
+
+ int w = image.getWidth();
+ int h = image.getHeight();
+
+ if (w != frame.getWidth() || h != frame.getHeight()) {
+ throw new RuntimeException("Wrong image size!");
+ }
+
+ if (image.getRGB(w / 4, h / 4) != COLORS[0].getRGB()) {
+ throw new RuntimeException("Wrong image color!");
+ }
+
+ if (image.getRGB(3 * w / 4, h / 4) != COLORS[1].getRGB()) {
+ throw new RuntimeException("Wrong image color!");
+ }
+
+ if (image.getRGB(w / 4, 3 * h / 4) != COLORS[2].getRGB()) {
+ throw new RuntimeException("Wrong image color!");
+ }
+
+ if (image.getRGB(3 * w / 4, 3 * h / 4) != COLORS[3].getRGB()) {
+ throw new RuntimeException("Wrong image color!");
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/font/TextLayout/OSXLigatureTest.java Tue Nov 17 13:09:16 2015 -0800
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, 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 7162125
+ * @summary Test ligatures form on OS X.
+ */
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.awt.font.TextAttribute;
+import java.util.HashMap;
+import java.util.Map;
+
+public class OSXLigatureTest {
+
+ public static void main(String[] args) {
+ if (!System.getProperty("os.name").startsWith("Mac")) {
+ return;
+ }
+ String ligStr = "ffi";
+ int w = 50, h = 50;
+
+ BufferedImage bi1 = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+ Graphics2D bi1Graphics = bi1.createGraphics();
+ bi1Graphics.setColor(Color.white);
+ bi1Graphics.fillRect(0, 0, w, h);
+ bi1Graphics.setColor(Color.black);
+ Font noLigFont = new Font("Gill Sans", Font.PLAIN, 30);
+ bi1Graphics.setFont(noLigFont);
+ bi1Graphics.drawString(ligStr, 10, 40);
+
+ BufferedImage bi2 = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+ Graphics2D bi2Graphics = bi2.createGraphics();
+ bi2Graphics.setColor(Color.white);
+ bi2Graphics.fillRect(0, 0, w, h);
+ bi2Graphics.setColor(Color.black);
+ Map<TextAttribute, Object> attributes = new HashMap<>();
+ attributes.put(TextAttribute.LIGATURES, TextAttribute.LIGATURES_ON);
+ Font ligFont = noLigFont.deriveFont(attributes);
+ bi2Graphics.setFont(ligFont);
+ bi2Graphics.drawString(ligStr, 10, 40);
+
+ boolean same = true;
+ for (int x = 0; x < w; x++) {
+ for (int y = 0; y < h; y++) {
+ int c1 = bi1.getRGB(x, y);
+ int c2 = bi2.getRGB(x, y);
+ same &= (c1 == c2);
+ }
+ if (!same) {
+ break;
+ }
+ }
+ if (same) {
+ throw new RuntimeException("Images do not differ - no ligature");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/hidpi/properties/HiDPIPropertiesLinuxTest.java Tue Nov 17 13:09:16 2015 -0800
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, 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 java.awt.Dialog;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import javax.swing.UIManager;
+
+/* @test
+ * @bug 8137571
+ * @summary Linux HiDPI Graphics support
+ * @author Alexander Scherbatiy
+ * @requires (os.family == "linux")
+ * @run main/othervm -Dsun.java2d.uiScale.enabled=false
+ * -Dsun.java2d.uiScale=2
+ * HiDPIPropertiesLinuxTest UISCALE_DISABLED
+ * HiDPIPropertiesTest UISCALE_DISABLED
+ * @run main/othervm -Dsun.java2d.uiScale.enabled=true
+ * -Dsun.java2d.uiScale=3
+ * HiDPIPropertiesLinuxTest UISCALE_3
+ * @run main/othervm -Dsun.java2d.uiScale=4
+ * HiDPIPropertiesLinuxTest UISCALE_4
+ */
+public class HiDPIPropertiesLinuxTest {
+
+ public static void main(String[] args) throws Exception {
+
+ try {
+ UIManager.setLookAndFeel(
+ "com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
+ } catch (Exception e) {
+ return;
+ }
+
+ String testCase = args[0];
+ switch (testCase) {
+ case "UISCALE_DISABLED":
+ testScale(1.0, 1.0);
+ break;
+ case "UISCALE_3":
+ testScale(3.0, 3.0);
+ break;
+ case "UISCALE_4":
+ testScale(4.0, 4.0);
+ break;
+ default:
+ throw new RuntimeException("Unknown test case: " + testCase);
+ }
+ }
+
+ private static void testScale(double scaleX, double scaleY) {
+
+ Dialog dialog = new Dialog((Frame) null, true) {
+
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+ AffineTransform tx = ((Graphics2D) g).getTransform();
+ dispose();
+ if (scaleX != tx.getScaleX() || scaleY != tx.getScaleY()) {
+ throw new RuntimeException(String.format("Wrong scale:"
+ + "[%f, %f] instead of [%f, %f].",
+ tx.getScaleX(), tx.getScaleY(), scaleX, scaleY));
+ }
+ }
+ };
+ dialog.setSize(200, 300);
+ dialog.setVisible(true);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/hidpi/properties/HiDPIPropertiesWindowsTest.java Tue Nov 17 13:09:16 2015 -0800
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2015, 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 java.awt.Dialog;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import javax.swing.UIManager;
+
+/* @test
+ * @bug 8073320
+ * @summary Windows HiDPI support
+ * @author Alexander Scherbatiy
+ * @requires (os.family == "windows")
+ * @run main/othervm -Dsun.java2d.uiScale.enabled=false
+ * -Dsun.java2d.win.uiScaleX=3 -Dsun.java2d.win.uiScaleY=2
+ * HiDPIPropertiesWindowsTest UISCALE_DISABLED
+ * @run main/othervm -Dsun.java2d.uiScale.enabled=false
+ * -Dsun.java2d.uiScale=3
+ * HiDPIPropertiesWindowsTest UISCALE_DISABLED
+ * @run main/othervm -Dsun.java2d.uiScale.enabled=false
+ * -Dsun.java2d.uiScale=3
+ * -Dsun.java2d.win.uiScaleX=5 -Dsun.java2d.win.uiScaleY=6
+ * HiDPIPropertiesWindowsTest UISCALE_DISABLED
+ * @run main/othervm -Dsun.java2d.uiScale.enabled=true
+ * -Dsun.java2d.uiScale=3
+ * HiDPIPropertiesWindowsTest UISCALE_3
+ * @run main/othervm -Dsun.java2d.uiScale.enabled=true
+ * -Dsun.java2d.uiScale=4
+ * -Dsun.java2d.win.uiScaleX=2 -Dsun.java2d.win.uiScaleY=3
+ * HiDPIPropertiesWindowsTest UISCALE_2X3
+ * @run main/othervm -Dsun.java2d.uiScale.enabled=true
+ * -Dsun.java2d.win.uiScaleX=3 -Dsun.java2d.win.uiScaleY=2
+ * HiDPIPropertiesWindowsTest UISCALE_3X2
+ * @run main/othervm -Dsun.java2d.uiScale=4
+ * HiDPIPropertiesWindowsTest UISCALE_4
+ * @run main/othervm -Dsun.java2d.uiScale=4
+ * -Dsun.java2d.win.uiScaleX=2 -Dsun.java2d.win.uiScaleY=3
+ * HiDPIPropertiesWindowsTest UISCALE_2X3
+ * @run main/othervm -Dsun.java2d.win.uiScaleX=4 -Dsun.java2d.win.uiScaleY=5
+ * HiDPIPropertiesWindowsTest UISCALE_4X5
+ * @run main/othervm -Dsun.java2d.uiScale=3
+ * -Dsun.java2d.win.uiScaleX=0 -Dsun.java2d.win.uiScaleY=0
+ * HiDPIPropertiesWindowsTest UISCALE_3
+ * @run main/othervm -Dsun.java2d.uiScale=4
+ * -Dsun.java2d.win.uiScaleX=-7 -Dsun.java2d.win.uiScaleY=-8
+ * HiDPIPropertiesWindowsTest UISCALE_4
+ * @run main/othervm -Dsun.java2d.uiScale=4x
+ * HiDPIPropertiesWindowsTest UISCALE_4
+ * @run main/othervm -Dsun.java2d.win.uiScaleX=4x -Dsun.java2d.win.uiScaleY=5x
+ * HiDPIPropertiesWindowsTest UISCALE_4X5
+ * @run main/othervm -Dsun.java2d.uiScale=384dpi
+ * HiDPIPropertiesWindowsTest UISCALE_4
+ * @run main/othervm -Dsun.java2d.uiScale=300%
+ * HiDPIPropertiesWindowsTest UISCALE_3
+ * @run main/othervm -Dsun.java2d.win.uiScaleX=400% -Dsun.java2d.win.uiScaleY=500%
+ * HiDPIPropertiesWindowsTest UISCALE_4X5
+ * @run main/othervm -Dsun.java2d.win.uiScaleX=288dpi -Dsun.java2d.win.uiScaleY=192dpi
+ * HiDPIPropertiesWindowsTest UISCALE_3X2
+ * @run main/othervm -Dsun.java2d.win.uiScaleX=200% -Dsun.java2d.win.uiScaleY=288dpi
+ * HiDPIPropertiesWindowsTest UISCALE_2X3
+ */
+public class HiDPIPropertiesWindowsTest {
+
+ public static void main(String[] args) throws Exception {
+
+ try {
+ UIManager.setLookAndFeel(
+ "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
+ } catch (Exception e) {
+ return;
+ }
+
+ String testCase = args[0];
+ switch (testCase) {
+ case "UISCALE_DISABLED":
+ testScale(1.0, 1.0);
+ break;
+ case "UISCALE_3":
+ testScale(3.0, 3.0);
+ break;
+ case "UISCALE_4":
+ testScale(4.0, 4.0);
+ break;
+ case "UISCALE_2X3":
+ testScale(2.0, 3.0);
+ break;
+ case "UISCALE_3X2":
+ testScale(3.0, 2.0);
+ break;
+ case "UISCALE_4X5":
+ testScale(4.0, 5.0);
+ break;
+ default:
+ throw new RuntimeException("Unknown test case: " + testCase);
+ }
+ }
+
+ private static void testScale(double scaleX, double scaleY) {
+
+ Dialog dialog = new Dialog((Frame) null, true) {
+
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+ AffineTransform tx = ((Graphics2D) g).getTransform();
+ dispose();
+ if (scaleX != tx.getScaleX() || scaleY != tx.getScaleY()) {
+ throw new RuntimeException(String.format("Wrong scale:"
+ + "[%f, %f] instead of [%f, %f].",
+ tx.getScaleX(), tx.getScaleY(), scaleX, scaleY));
+ }
+ }
+ };
+ dialog.setSize(200, 300);
+ dialog.setVisible(true);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/image/MultiResolutionImage/MultiResolutionDrawImageWithTransformTest.java Tue Nov 17 13:09:16 2015 -0800
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2015, 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 java.awt.Color;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import java.awt.image.BaseMultiResolutionImage;
+import static java.awt.RenderingHints.KEY_RESOLUTION_VARIANT;
+import static java.awt.RenderingHints.VALUE_RESOLUTION_VARIANT_SIZE_FIT;
+import java.awt.geom.AffineTransform;
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+import sun.java2d.StateTrackable;
+import sun.java2d.SunGraphics2D;
+import sun.java2d.SurfaceData;
+import sun.java2d.loops.SurfaceType;
+
+/**
+ * @test
+ * @bug 8073320
+ * @author Alexander Scherbatiy
+ * @summary Windows HiDPI support
+ * @modules java.desktop/sun.java2d java.desktop/sun.java2d.loops
+ * @run main MultiResolutionDrawImageWithTransformTest
+ */
+public class MultiResolutionDrawImageWithTransformTest {
+
+ private static final int SCREEN_SIZE = 400;
+ private static final int IMAGE_SIZE = SCREEN_SIZE / 4;
+ private static final Color BACKGROUND_COLOR = Color.PINK;
+ private static final Color[] COLORS = {
+ Color.CYAN, Color.GREEN, Color.BLUE, Color.ORANGE
+ };
+
+ public static void main(String[] args) throws Exception {
+
+ int length = COLORS.length;
+ BufferedImage[] resolutionVariants = new BufferedImage[length];
+ for (int i = 0; i < length; i++) {
+ resolutionVariants[i] = createRVImage(getSize(i), COLORS[i]);
+ }
+
+ BaseMultiResolutionImage mrImage = new BaseMultiResolutionImage(
+ resolutionVariants);
+
+ // scale 1, transform 1, resolution variant 1
+ Color color = getImageColor(mrImage, 1, 1);
+ if (!getColorForScale(1).equals(color)) {
+ throw new RuntimeException("Wrong resolution variant!");
+ }
+
+ // scale 1, transform 2, resolution variant 2
+ color = getImageColor(mrImage, 1, 2);
+ if (!getColorForScale(2).equals(color)) {
+ throw new RuntimeException("Wrong resolution variant!");
+ }
+
+ // scale 2, transform 1, resolution variant 2
+ color = getImageColor(mrImage, 2, 1);
+ if (!getColorForScale(2).equals(color)) {
+ throw new RuntimeException("Wrong resolution variant!");
+ }
+
+ // scale 2, transform 2, resolution variant 4
+ color = getImageColor(mrImage, 2, 2);
+ if (!getColorForScale(4).equals(color)) {
+ throw new RuntimeException("Wrong resolution variant!");
+ }
+ }
+
+ private static Color getColorForScale(int scale) {
+ return COLORS[scale - 1];
+ }
+
+ private static Color getImageColor(Image image, double configScale,
+ double transformScale) {
+
+ TestSurfaceData surface = new TestSurfaceData(SCREEN_SIZE, SCREEN_SIZE,
+ configScale);
+ SunGraphics2D g2d = new SunGraphics2D(surface,
+ Color.BLACK, Color.BLACK, null);
+ g2d.setRenderingHint(KEY_RESOLUTION_VARIANT,
+ VALUE_RESOLUTION_VARIANT_SIZE_FIT);
+ AffineTransform tx = AffineTransform.getScaleInstance(transformScale,
+ transformScale);
+ g2d.drawImage(image, tx, null);
+ g2d.dispose();
+
+ int backgroundX = (int) (1.5 * image.getWidth(null) * transformScale);
+ int backgroundY = (int) (1.5 * image.getHeight(null) * transformScale);
+ Color backgroundColor = surface.getColor(backgroundX, backgroundY);
+ //surface.show(String.format("Config: %f, transform: %f", configScale, transformScale));
+ if (!BACKGROUND_COLOR.equals(backgroundColor)) {
+ throw new RuntimeException("Wrong background color!");
+ }
+ return surface.getColor(IMAGE_SIZE / 4, IMAGE_SIZE / 4);
+ }
+
+ private static int getSize(int i) {
+ return (i + 1) * IMAGE_SIZE;
+ }
+
+ private static BufferedImage createRVImage(int size, Color color) {
+ BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
+ Graphics g = image.createGraphics();
+ g.setColor(color);
+ g.fillRect(0, 0, size, size);
+ g.dispose();
+ return image;
+ }
+
+ static class TestGraphicsConfig extends GraphicsConfiguration {
+
+ private final double scale;
+
+ TestGraphicsConfig(double scale) {
+ this.scale = scale;
+ }
+
+ @Override
+ public GraphicsDevice getDevice() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public ColorModel getColorModel() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public ColorModel getColorModel(int transparency) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public AffineTransform getDefaultTransform() {
+ return AffineTransform.getScaleInstance(scale, scale);
+ }
+
+ @Override
+ public AffineTransform getNormalizingTransform() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Rectangle getBounds() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }
+
+ static class TestSurfaceData extends SurfaceData {
+
+ private final int width;
+ private final int height;
+ private final GraphicsConfiguration gc;
+ private final BufferedImage buffImage;
+ private final double scale;
+
+ public TestSurfaceData(int width, int height, double scale) {
+ super(StateTrackable.State.DYNAMIC, SurfaceType.Custom, ColorModel.getRGBdefault());
+ this.scale = scale;
+ gc = new TestGraphicsConfig(scale);
+ this.width = (int) Math.ceil(scale * width);
+ this.height = (int) Math.ceil(scale * height);
+ buffImage = new BufferedImage(this.width, this.height,
+ BufferedImage.TYPE_INT_RGB);
+
+ Graphics imageGraphics = buffImage.createGraphics();
+ imageGraphics.setColor(BACKGROUND_COLOR);
+ imageGraphics.fillRect(0, 0, this.width, this.height);
+ imageGraphics.dispose();
+ }
+
+ Color getColor(int x, int y) {
+ int sx = (int) Math.ceil(x * scale);
+ int sy = (int) Math.ceil(y * scale);
+ return new Color(buffImage.getRGB(sx, sy));
+ }
+
+ @Override
+ public SurfaceData getReplacement() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public GraphicsConfiguration getDeviceConfiguration() {
+ return gc;
+ }
+
+ @Override
+ public Raster getRaster(int x, int y, int w, int h) {
+ return buffImage.getRaster();
+ }
+
+ @Override
+ public Rectangle getBounds() {
+ return new Rectangle(0, 0, width, height);
+ }
+
+ @Override
+ public Object getDestination() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ private void show(String title) {
+ Frame frame = new Frame() {
+
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+ g.drawImage(buffImage, 0, 0, this);
+ g.setColor(Color.GRAY);
+ g.drawRect(0, 0, width, height);
+ g.drawRect(0, height / 2, width, height / 2);
+ g.drawRect(width / 2, 0, width / 2, height);
+ }
+ };
+ frame.setTitle(title);
+ frame.setSize(width, height);
+ frame.setVisible(true);
+ }
+ }
+}
--- a/jdk/test/java/awt/print/PageFormat/ImageableAreaTest.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/test/java/awt/print/PageFormat/ImageableAreaTest.java Tue Nov 17 13:09:16 2015 -0800
@@ -45,7 +45,7 @@
/**
* @test
- * @bug 8044444
+ * @bug 8044444 8081491
* @summary The output's 'Page-n' footer does not show completely
* @author Alexandr Scherbatiy
* @run main/manual ImageableAreaTest
@@ -58,11 +58,13 @@
@Override
public void run() {
+
createAndShowTestDialog(
"1. Press the Print Table button\n"
+ " Java print dialog should appear.\n"
+ "2. Press the Print button on the Java Print dialog.\n"
- + "2. Check that the page number is correctly printed.\n"
+ + "3. Check that the page number is correctly printed.\n"
+ + "4. Check only the visible part of the table is printed.\n"
+ "If so, press PASS, else press FAIL.",
"Page number is not correctly printed!",
ImageableAreaTest::printWithJavaPrintDialog);
@@ -71,24 +73,47 @@
"1. Press the Print Table button\n"
+ " The table should be printed without the print dialog.\n"
+ "2. Check that the page number is correctly printed.\n"
+ + "3. Check only the visible part of the table is printed.\n"
+ "If so, press PASS, else press FAIL.",
"Page number is not correctly printed!",
ImageableAreaTest::printWithoutPrintDialog);
+
+
createAndShowTestDialog(
"1. Press the Print Table button\n"
+ " Java print dialog should appear.\n"
+ "2. Press the Print button on the Java Print dialog.\n"
+ "3. Check that the table has about half size of the printed page\n"
+ + "4. Check only the visible part of the table is printed.\n"
+ "If so, press PASS, else press FAIL.",
"Custom imageable area is not correctly printed!",
ImageableAreaTest::printWithCustomImageareaSize);
+
+ createAndShowTestDialog(
+ "1. Press the Print Table button\n"
+ + " Java print dialog should appear.\n"
+ + "2. Press the Print button on the Java Print dialog.\n"
+ + "3. Check that the rows with different height is printed.\n"
+ + "4. Check only the visible part of the table is printed.\n"
+ + "If so, press PASS, else press FAIL.",
+ "Row with different height is not correctly printed!",
+ ImageableAreaTest::printDifferentRowHeight);
+
+ createAndShowTestDialog(
+ "1. Press the Print Table button\n"
+ + " Java print dialog should appear.\n"
+ + "2. Press the Print button on the Java Print dialog.\n"
+ + "3. Check that the only 1 row is shown & printed.\n"
+ + "If so, press PASS, else press FAIL.",
+ "Only 1 Row is not correctly printed!",
+ ImageableAreaTest::printOneRowWithJavaPrintDialog);
}
});
}
private static void printWithJavaPrintDialog() {
- final JTable table = createAuthorTable(42);
+ final JTable table = createAuthorTable(50);
Printable printable = table.getPrintable(
JTable.PrintMode.NORMAL,
new MessageFormat("Author Table"),
@@ -110,7 +135,7 @@
private static void printWithoutPrintDialog() {
- final JTable table = createAuthorTable(42);
+ final JTable table = createAuthorTable(50);
PrintRequestAttributeSet pras
= new HashPrintRequestAttributeSet();
pras.add(new Copies(1));
@@ -132,6 +157,50 @@
}
}
+ private static void printDifferentRowHeight() {
+ final JTable table = createAuthorTable(50);
+ table.setRowHeight(15, table.getRowHeight(15)+10);
+ Printable printable = table.getPrintable(
+ JTable.PrintMode.NORMAL,
+ new MessageFormat("Author Table"),
+ new MessageFormat("Page - {0}"));
+
+ PrinterJob job = PrinterJob.getPrinterJob();
+ job.setPrintable(printable);
+
+ boolean printAccepted = job.printDialog();
+ if (printAccepted) {
+ try {
+ job.print();
+ closeFrame();
+ } catch (PrinterException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ }
+
+ private static void printOneRowWithJavaPrintDialog() {
+ final JTable table = createAuthorTable(1);
+ Printable printable = table.getPrintable(
+ JTable.PrintMode.NORMAL,
+ new MessageFormat("Author Table"),
+ new MessageFormat("Page - {0}"));
+
+ PrinterJob job = PrinterJob.getPrinterJob();
+ job.setPrintable(printable);
+
+ boolean printAccepted = job.printDialog();
+ if (printAccepted) {
+ try {
+ job.print();
+ closeFrame();
+ } catch (PrinterException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
private static void printWithCustomImageareaSize() {
final JTable table = createAuthorTable(18);
PrintRequestAttributeSet printAttributes = new HashPrintRequestAttributeSet();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/PageDlgStackOverflowTest.java Tue Nov 17 13:09:16 2015 -0800
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, 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 java.awt.print.PrinterJob;
+import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
+import javax.print.attribute.standard.DialogTypeSelection;
+
+/**
+ * @test
+ * @bug 8039412
+ * @run main/manual PageDlgStackOverflowTest
+ * @summary Calling pageDialog() after printDialog with
+ * DialogTypeSelection.NATIVE should not result in StackOverflowError
+ */
+public class PageDlgStackOverflowTest {
+
+ public static void main(String args[]) {
+ PrinterJob job = PrinterJob.getPrinterJob();
+ if (job == null) {
+ return;
+ }
+ PrintRequestAttributeSet pSet =
+ new HashPrintRequestAttributeSet();
+ pSet.add(DialogTypeSelection.NATIVE);
+ job.printDialog(pSet);
+ try {
+ job.pageDialog(pSet);
+ } catch (StackOverflowError e) {
+ throw new RuntimeException("StackOverflowError is thrown");
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JInternalFrame/6288609/TestJInternalFrameDispose.java Tue Nov 17 13:09:16 2015 -0800
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015, 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 6288609
+ * @summary JInternalFrame.setDefaultCloseOperation() interferes with "close"
+ behavior
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main TestJInternalFrameDispose
+ */
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
+import javax.swing.JFrame;
+import javax.swing.JDesktopPane;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JInternalFrame;
+import javax.swing.SwingUtilities;
+import javax.swing.event.InternalFrameAdapter;
+import javax.swing.event.InternalFrameEvent;
+
+public class TestJInternalFrameDispose {
+
+ private static JDesktopPane desktopPane;
+ private static JFrame frame = new JFrame("Test Frame");
+ private static int count = 0;
+ private static JMenu menu;
+ private static JMenuBar menuBar;
+ private static JMenuItem menuItem;
+ private static Robot robot;
+ private static JInternalFrame internalFrame;
+
+ public static void main(String[] args) throws Exception {
+ robot = new Robot();
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ createUI();
+ }
+ });
+
+ robot.waitForIdle();
+ executeTest();
+ dispose();
+ }
+
+ private static void createUI() {
+
+ desktopPane = new JDesktopPane();
+ frame.getContentPane().add(desktopPane);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ menuBar = new JMenuBar();
+ frame.setJMenuBar(menuBar);
+
+ menu = new JMenu("File");
+ menuBar.add(menu);
+
+ menuItem = new JMenuItem("New Child");
+ menuItem.addActionListener(
+ new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JInternalFrame f = new JInternalFrame("Child "
+ + (++count), true, true, true, true);
+ f.setDefaultCloseOperation(
+ JInternalFrame.DO_NOTHING_ON_CLOSE);
+ f.addInternalFrameListener(new InternalFrameAdapter() {
+ @Override
+ public void internalFrameClosing(
+ InternalFrameEvent e) {
+ e.getInternalFrame().dispose();
+ }
+ });
+ f.setSize(200, 300);
+ f.setLocation(count * 20, count * 20);
+ desktopPane.add(f);
+ f.setVisible(true);
+ }
+ });
+ menu.add(menuItem);
+
+ frame.setSize(400, 500);
+ frame.setLocationRelativeTo(null);
+ frame.setVisible(true);
+ }
+
+ private static void executeTest() throws Exception {
+
+ Point point = Util.getCenterPoint(menu);
+ performMouseOperations(point);
+ point = Util.getCenterPoint(menuItem);
+ performMouseOperations(point);
+ point = Util.getCenterPoint(menu);
+ performMouseOperations(point);
+ point = Util.getCenterPoint(menuItem);
+ performMouseOperations(point);
+ SwingUtilities.invokeAndWait(new Runnable() {
+
+ @Override
+ public void run() {
+ internalFrame = desktopPane.getSelectedFrame();
+ internalFrame.doDefaultCloseAction();
+ internalFrame = desktopPane.getSelectedFrame();
+ }
+ });
+
+ robot.delay(2000);
+ if (internalFrame == null) {
+ dispose();
+ throw new RuntimeException("Test Failed");
+ }
+ }
+
+ private static void dispose() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+
+ @Override
+ public void run() {
+ frame.dispose();
+ }
+ });
+ }
+
+ private static void performMouseOperations(Point point) {
+ robot.mouseMove(point.x, point.y);
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ robot.delay(1000);
+ robot.waitForIdle();
+ }
+}
--- a/jdk/test/javax/swing/JRadioButton/FocusTraversal/FocusTraversal.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/test/javax/swing/JRadioButton/FocusTraversal/FocusTraversal.java Tue Nov 17 13:09:16 2015 -0800
@@ -22,43 +22,82 @@
*/
/* @test
- @bug 8129940
- @summary JRadioButton does not honor non-standard FocusTraversalKeys
- @author Semyon Sadetsky
- */
-
-import javax.swing.*;
-import java.awt.*;
+ @bug 8129940 8132770
+ @summary JRadioButton should run custom FocusTraversalKeys for all LaFs
+ @run main FocusTraversal
+ */
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.KeyboardFocusManager;
+import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;
+import javax.swing.ButtonGroup;
+import javax.swing.FocusManager;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+import javax.swing.KeyStroke;
+import javax.swing.LookAndFeel;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
public class FocusTraversal {
private static JFrame frame;
private static JRadioButton a;
+ private static JRadioButton b;
+ private static JRadioButton c;
private static JRadioButton d;
private static JTextField next;
private static JTextField prev;
+ private static Robot robot;
public static void main(String[] args) throws Exception {
+
+ robot = new Robot();
+ robot.delay(2000);
+ UIManager.LookAndFeelInfo[] lookAndFeelArray
+ = UIManager.getInstalledLookAndFeels();
+ for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) {
+ executeCase(lookAndFeelItem.getClassName());
+ }
+ }
+
+ private static void executeCase(String lookAndFeelString)
+ throws Exception {
+ if (tryLookAndFeel(lookAndFeelString)) {
+ createUI(lookAndFeelString);
+ robot.delay(2000);
+ runTestCase();
+ robot.delay(2000);
+ cleanUp();
+ robot.delay(2000);
+ }
+ }
+
+ private static void createUI(final String lookAndFeelString)
+ throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
- frame = new JFrame("FocusTraversalTest");
- frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
- frame.setUndecorated(true);
-
Set<KeyStroke> keystrokes = new HashSet<KeyStroke>();
keystrokes.add(KeyStroke.getKeyStroke("TAB"));
keystrokes.add(KeyStroke.getKeyStroke("ENTER"));
+ frame = new JFrame("FocusTraversalTest " + lookAndFeelString);
+ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ frame.setUndecorated(true);
frame.setFocusTraversalKeys(
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
keystrokes);
a = new JRadioButton("a");
- JRadioButton b = new JRadioButton("b");
- JRadioButton c = new JRadioButton("c");
+ b = new JRadioButton("b");
+ c = new JRadioButton("c");
d = new JRadioButton("d");
ButtonGroup radioButtonGroup = new ButtonGroup();
@@ -84,61 +123,102 @@
frame.add(root);
frame.pack();
+ frame.setLocationRelativeTo(null);
frame.setVisible(true);
- }
- });
-
- SwingUtilities.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- a.requestFocus();
+ frame.toFront();
}
});
+ }
- Robot robot = new Robot();
- robot.waitForIdle();
+ private static void runTestCase() throws Exception {
+ LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
+ focusOn(a);
+ if (isExcludedLookAndFeel(lookAndFeel)) {
+ robot.keyPress(KeyEvent.VK_ENTER);
+ robot.keyRelease(KeyEvent.VK_ENTER);
+ robot.waitForIdle();
+ isFocusOwner(b, "forward");
+ robot.keyPress(KeyEvent.VK_SHIFT);
+ robot.keyPress(KeyEvent.VK_TAB);
+ robot.keyRelease(KeyEvent.VK_TAB);
+ robot.keyRelease(KeyEvent.VK_SHIFT);
+ robot.waitForIdle();
+ isFocusOwner(a, "backward");
+
+ } else {
- robot.setAutoDelay(200);
+ robot.keyPress(KeyEvent.VK_ENTER);
+ robot.keyRelease(KeyEvent.VK_ENTER);
+ robot.waitForIdle();
+ isFocusOwner(next, "forward");
+ robot.keyPress(KeyEvent.VK_SHIFT);
+ robot.keyPress(KeyEvent.VK_TAB);
+ robot.keyRelease(KeyEvent.VK_TAB);
+ robot.keyRelease(KeyEvent.VK_SHIFT);
+ robot.waitForIdle();
+ isFocusOwner(d, "backward");
+ }
- robot.keyPress(KeyEvent.VK_ENTER);
- robot.keyRelease(KeyEvent.VK_ENTER);
- robot.waitForIdle();
+ }
+
+ private static boolean isExcludedLookAndFeel(LookAndFeel lookAndFeel) {
+ return lookAndFeel.toString().toLowerCase().contains("aqua")
+ || lookAndFeel.toString().toLowerCase().contains("nimbus")
+ || lookAndFeel.toString().toLowerCase().contains("gtk");
+ }
+
+ private static void focusOn(Component component)
+ throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
- Component focusOwner =
- FocusManager.getCurrentManager().getFocusOwner();
- if (focusOwner != next) {
+ component.requestFocusInWindow();
+ }
+ });
+ }
+
+ private static void isFocusOwner(Component queriedFocusOwner,
+ String direction)
+ throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ Component actualFocusOwner
+ = FocusManager.getCurrentManager().getFocusOwner();
+ if (actualFocusOwner != queriedFocusOwner) {
+ frame.dispose();
throw new RuntimeException(
- "Focus component is wrong after forward key " + focusOwner);
+ "Focus component is wrong after " + direction
+ + " direction ");
+
}
}
});
+ }
- robot.keyPress(KeyEvent.VK_SHIFT);
- robot.keyPress(KeyEvent.VK_TAB);
- robot.keyRelease(KeyEvent.VK_TAB);
- robot.keyRelease(KeyEvent.VK_SHIFT);
- robot.waitForIdle();
+ private static boolean tryLookAndFeel(String lookAndFeelString)
+ throws Exception {
+
+ try {
+ UIManager.setLookAndFeel(
+ lookAndFeelString);
+
+ } catch (UnsupportedLookAndFeelException
+ | ClassNotFoundException
+ | InstantiationException
+ | IllegalAccessException e) {
+ return false;
+ }
+ return true;
+ }
+
+ private static void cleanUp() throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
- Component focusOwner =
- FocusManager.getCurrentManager().getFocusOwner();
- if (focusOwner != d) {
- throw new RuntimeException(
- "Focus component is wrong after backward key " + focusOwner);
- }
- }
- });
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() {
frame.dispose();
}
});
- System.out.println("ok");
-
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTabbedPane/8134116/Bug8134116.java Tue Nov 17 13:09:16 2015 -0800
@@ -0,0 +1,130 @@
+
+import java.awt.*;
+import java.awt.event.KeyEvent;
+import java.util.ArrayList;
+import java.util.List;
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleComponent;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+import javax.swing.*;
+import javax.swing.plaf.nimbus.NimbusLookAndFeel;
+
+/*
+ * @test
+ * @bug 8134116
+ * @summary JTabbedPane$Page.getBounds throws IndexOutOfBoundsException
+ * @run main Bug8134116
+ */
+public class Bug8134116 {
+
+ public static void main(String args[]) throws Exception {
+
+ try {
+ UIManager.setLookAndFeel(new NimbusLookAndFeel());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ SwingUtilities.invokeAndWait(() -> {
+ JPanel panel0 = new JPanel();
+ BadPane badPane = new BadPane();
+ badPane.add("zero", panel0);
+ badPane.add("one", null);
+ JFrame frame = new JFrame();
+ frame.add(badPane);
+ frame.setSize(300, 300);
+ frame.setVisible(true);
+
+ AccessibleContext ac = badPane.getAccessibleContext();
+ Accessible page0 = ac.getAccessibleChild(0);
+ if (page0 == null) {
+ // Not something being tested, but checking anyway
+ throw new RuntimeException("getAccessibleChild(0) is null");
+ }
+ Accessible page1 = ac.getAccessibleChild(1);
+ if (page1 == null) {
+ // Not something being tested, but checking anyway
+ throw new RuntimeException("getAccessibleChild(1) is null");
+ }
+ // page0 and page1 are a JTabbedPane.Page, a private inner class
+ // and is an AccessibleContext
+ // and implements Accessible and AccessibleComponent
+ AccessibleContext pac0 = page0.getAccessibleContext();
+ AccessibleContext pac1 = page1.getAccessibleContext();
+
+ // the following would fail if JDK-8134116 fix not present
+
+ // test Page.getBounds
+ // ensure no IndexOutOfBoundsException
+ pac0.getAccessibleComponent().getBounds();
+
+ // test Page.getAccessibleStateSet
+ // At this point page 0 is selected
+ AccessibleStateSet accSS0 = pac0.getAccessibleStateSet();
+ if (!accSS0.contains(AccessibleState.SELECTED)) {
+ String msg = "Empty title -> AccessibleState.SELECTED not set";
+ throw new RuntimeException(msg);
+ }
+
+ // test Page.getAccessibleIndexInParent
+ if (pac0.getAccessibleIndexInParent() == -1) {
+ String msg = "Empty title -> negative AccessibleIndexInParent";
+ throw new RuntimeException(msg);
+ }
+
+ // test Page.getAccessibleName
+ String accName = pac0.getAccessibleName();
+ if (!accName.equals("zero")) {
+ String msg = "Empty title -> empty AccessibleName";
+ throw new RuntimeException(msg);
+ }
+ // test Page.getAccessibleName when component is null
+ accName = pac1.getAccessibleName();
+ if (!accName.equals("one")) {
+ String msg = "AccessibleName of null panel not 'one'";
+ throw new RuntimeException(msg);
+ }
+
+ // test Page.setDisplayedMnemonicIndex
+ // Empty title -> IllegalArgumnetException
+ badPane.setDisplayedMnemonicIndexAt(0, 1);
+
+ // test Page.updateDisplayedMnemonicIndex
+ badPane.setMnemonicAt(0, KeyEvent.VK_Z);
+ if (badPane.getDisplayedMnemonicIndexAt(0) == -1) {
+ String msg="Empty title -> getDisplayedMnemonicIndexAt failure";
+ throw new RuntimeException(msg);
+ }
+ });
+ }
+
+ // The following is likely what is being done in Burp Suite
+ // https://portswigger.net/burp/ which fails in the same way, i.e. the
+ // pages List in JTabbedPane is not being managed properly and thus
+ // Page.title is "" for each page. The overridden insertTab manages titles
+ // in the subclass passing a "" title to the superclass JTabbedPane through
+ // its insertTab. Later an overridden getTitleAt returns the titles as
+ // managed by the subclass.
+ static class BadPane extends JTabbedPane {
+ private List<String> titles;
+
+ BadPane() {
+ titles = new ArrayList<String>(1);
+ }
+
+ @Override
+ public void insertTab( String title, Icon icon, Component component,
+ String tip, int index ) {
+ titles.add(index, title);
+ super.insertTab("", icon, component, tip, index);
+ }
+
+ @Override
+ public String getTitleAt(int i) {
+ return titles.get(i);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTable/7124218/SelectEditTableCell.java Tue Nov 17 13:09:16 2015 -0800
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2015, 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 7124218
+ * @summary verifies different behaviour of SPACE and ENTER in JTable
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main SelectEditTableCell
+ */
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import javax.swing.DefaultListSelectionModel;
+import javax.swing.JFrame;
+import javax.swing.JTable;
+import javax.swing.LookAndFeel;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+
+public class SelectEditTableCell {
+
+ private static JFrame frame;
+ private static JTable table;
+ private static Robot robot;
+
+ public static void main(String[] args) throws Exception {
+ robot = new Robot();
+ robot.delay(2000);
+ UIManager.LookAndFeelInfo[] lookAndFeelArray
+ = UIManager.getInstalledLookAndFeels();
+ for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) {
+ executeCase(lookAndFeelItem.getClassName());
+ }
+
+ }
+
+ private static void executeCase(String lookAndFeelString) throws Exception {
+ if (tryLookAndFeel(lookAndFeelString)) {
+ createUI(lookAndFeelString);
+ robot.delay(2000);
+ runTestCase();
+ robot.delay(2000);
+ cleanUp();
+ robot.delay(2000);
+ }
+
+ }
+
+ private static void createUI(final String lookAndFeelString)
+ throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ String[][] data = {{"Foo"}};
+ String[] cols = {"One"};
+ table = new JTable(data, cols);
+ table.setSelectionMode(
+ DefaultListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+ frame = new JFrame(lookAndFeelString);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.getContentPane().add(table);
+ frame.pack();
+ frame.setSize(500, frame.getSize().height);
+ frame.setLocationRelativeTo(null);
+ frame.setVisible(true);
+ frame.toFront();
+ }
+ });
+ }
+
+ private static void runTestCase() throws Exception {
+ Point centerPoint;
+ centerPoint = Util.getCenterPoint(table);
+ LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
+ robot.mouseMove(centerPoint.x, centerPoint.y);
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ table.clearSelection();
+ if (table.isEditing() || table.isCellSelected(0, 0)) {
+ // assumption is bad, bail
+ frame.dispose();
+ throw new AssertionError("Failed assumption: assumed no"
+ + "editing and no selection.");
+ }
+ }
+ });
+ robot.waitForIdle();
+ int fetchKeyCode;
+ keyTap(fetchKeyCode = isMac(lookAndFeel)
+ ? KeyEvent.VK_ENTER : KeyEvent.VK_SPACE);
+ final int keyCode = fetchKeyCode;
+ robot.waitForIdle();
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ if (!table.isCellSelected(0, 0)) {
+ frame.dispose();
+ throw new RuntimeException(((keyCode == KeyEvent.VK_ENTER)
+ ? "Enter" : "Space")
+ + " should select cell");
+ }
+ }
+ });
+ robot.waitForIdle();
+ keyTap(KeyEvent.VK_SPACE);
+ robot.waitForIdle();
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ if (!table.isEditing()) {
+ frame.dispose();
+ throw new RuntimeException("Space should start editing");
+ }
+ table.getCellEditor().cancelCellEditing();
+ table.clearSelection();
+ if (table.isEditing() || table.isCellSelected(0, 0)) {
+ // assumption is bad, bail
+ frame.dispose();
+ throw new AssertionError("Failed assumption: assumed no "
+ + "editing and no selection.");
+ }
+ }
+ });
+ robot.waitForIdle();
+ // hitting a letter key will start editing
+ keyTap(KeyEvent.VK_A);
+ keyTap(KeyEvent.VK_SPACE);
+ keyTap(KeyEvent.VK_A);
+ robot.waitForIdle();
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ if (table.isCellSelected(0, 0)) {
+ frame.dispose();
+ throw new RuntimeException("Space should not select when "
+ + "already editing.");
+ }
+ }
+ });
+ }
+
+ private static void cleanUp() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ frame.dispose();
+ }
+ });
+ }
+
+ private static boolean isMac(LookAndFeel lookAndFeel) {
+
+ return lookAndFeel.toString().toLowerCase().contains("mac");
+ }
+
+ private static void keyTap(int keyCode) {
+ robot.keyPress(keyCode);
+ robot.keyRelease(keyCode);
+ }
+
+ private static boolean tryLookAndFeel(String lookAndFeelString)
+ throws Exception {
+ try {
+ UIManager.setLookAndFeel(
+ lookAndFeelString);
+
+ } catch (UnsupportedLookAndFeelException
+ | ClassNotFoundException
+ | InstantiationException
+ | IllegalAccessException e) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTable/JTableScrollTest.java Tue Nov 17 13:09:16 2015 -0800
@@ -0,0 +1,182 @@
+/* Copyright (c) 2015, 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 java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.Color;
+import java.awt.Dialog;
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JFrame;
+import javax.swing.JTable;
+import javax.swing.JTextArea;
+import javax.swing.JButton;
+import javax.swing.table.TableModel;
+import javax.swing.JScrollPane;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.SwingUtilities;
+
+/**
+ * @test
+ * @bug 8081491
+ * @summary Scrolling a JTable creates artifacts
+ * @run main/manual JTableScrollTest
+ */
+public class JTableScrollTest {
+ static JFrame frame = new JFrame();
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+
+ @Override
+ public void run() {
+ doTest(JTableScrollTest::createTable);
+ }
+ });
+ }
+
+ private static void createTable() {
+ // final
+ final String[] names = {
+ new String("first_name"),
+ new String("last_name"),
+ new String("favorite_color"),
+ new String("favorite_food")
+ };
+
+ // Create the dummy data (a few rows of names)
+ final Object[][] data = {
+ {"Mike", "Albers", "green", "strawberry"},
+ {"Mark", "Andrews", "blue", "grapes"},
+ {"Brian", "Beck", "black", "raspberry"},
+ {"Lara", "Bunni", "red", "strawberry"},
+ {"Roger", "Brinkley", "blue", "peach"},
+ {"Brent", "Christian", "black", "broccoli"},
+ {"Mark", "Davidson", "darkgreen", "asparagus"},
+ {"Jeff", "Dinkins", "blue", "kiwi"},
+ {"Ewan", "Dinkins", "yellow", "strawberry"},
+ {"Amy", "Fowler", "violet", "raspberry"},
+ {"Hania", "Gajewska", "purple", "raspberry"},
+ {"David", "Geary", "blue", "watermelon"},
+ {"Ryan", "Gosling", "pink", "donut"},
+ {"Eric", "Hawkes", "blue", "pickle"},
+ {"Shannon", "Hickey", "green", "grapes"},
+ {"Earl", "Johnson", "green", "carrot"},
+ {"Robi", "Khan", "green", "apple"},
+ {"Robert", "Kim", "blue", "strawberry"},
+ {"Janet", "Koenig", "turquoise", "peach"},
+ {"Jeff", "Kesselman", "blue", "pineapple"},
+ {"Onno", "Kluyt", "orange", "broccoli"},
+ {"Peter", "Korn", "sunpurple", "sparegrass"},
+ {"Rick", "Levenson", "black", "raspberry"},
+ {"Brian", "Lichtenwalter", "blue", "pear"},
+ {"Malini", "Minasandram", "beige", "corn"},
+ {"Michael", "Martak", "green", "strawberry"},
+ {"David", "Mendenhall", "forestgreen", "peach"},
+ {"Phil", "Milne", "pink", "banana"},
+ {"Lynn", "Monsanto", "cybergreen", "peach"},
+ {"Hans", "Muller", "rustred", "pineapple"},
+ {"Joshua", "Outwater", "blue", "pineapple"},
+ {"Tim", "Prinzing", "blue", "pepper"},
+ {"Raj", "Premkumar", "blue", "broccoli"},
+ {"Howard", "Rosen", "green", "strawberry"},
+ {"Ray", "Ryan", "black", "banana"},
+ {"Georges", "Saab", "aqua", "cantaloupe"},
+ {"Tom", "Santos", "blue", "pepper"},
+ {"Rich", "Schiavi", "blue", "pepper"},
+ {"Nancy", "Schorr", "green", "watermelon"},
+ {"Keith", "Sprochi", "darkgreen", "watermelon"},
+ {"Matt", "Tucker", "eblue", "broccoli"},
+ {"Dmitri", "Trembovetski", "red", "tomato"},
+ {"Scott", "Violet", "violet", "banana"},
+ {"Kathy", "Walrath", "darkgreen", "pear"},
+ };
+
+ // Create a model of the data.
+ TableModel dataModel = new AbstractTableModel() {
+ public int getColumnCount() { return names.length; }
+ public int getRowCount() { return data.length;}
+ public Object getValueAt(int row, int col) {return data[row][col];}
+ public String getColumnName(int column) {return names[column];}
+ public Class getColumnClass(int c) {return getValueAt(0, c).getClass();}
+ public boolean isCellEditable(int row, int col) {return col != 5;}
+ public void setValueAt(Object aValue, int row, int column) { data[row][column] = aValue; }
+ };
+
+ // Create the table
+ JTable tableView = new JTable(dataModel);
+ tableView.setBackground(Color.WHITE);
+ tableView.setForeground(Color.BLACK);
+ tableView.setSize(600, 800);
+ JScrollPane scrollpane = new JScrollPane(tableView);
+ frame.add(scrollpane);
+ frame.pack();
+ frame.setVisible(true);
+ }
+
+ private static void doTest(Runnable action) {
+ String description =
+ "JTable with rows will be displayed along with scrollbar.\n"
+ + "Scroll the table. Verify no arifacts are shown and rows.\n"
+ + " are correctly displayed.";
+ final JDialog dialog = new JDialog();
+ dialog.setTitle("ScrollArtifactTest ");
+ JTextArea textArea = new JTextArea(description);
+ textArea.setEditable(false);
+ final JButton testButton = new JButton("Create Table");
+ final JButton passButton = new JButton("PASS");
+ passButton.setEnabled(false);
+ passButton.addActionListener((e) -> {
+ dialog.dispose();
+ if (frame != null) {
+ frame.setVisible(false);
+ frame.dispose();
+ }
+ });
+ final JButton failButton = new JButton("FAIL");
+ failButton.setEnabled(false);
+ failButton.addActionListener((e) -> {
+ dialog.dispose();
+ if (frame != null) {
+ frame.setVisible(false);
+ frame.dispose();
+ }
+ throw new RuntimeException("Scrollbar artifact shown");
+ });
+ testButton.addActionListener((e) -> {
+ testButton.setEnabled(false);
+ action.run();
+ passButton.setEnabled(true);
+ failButton.setEnabled(true);
+ });
+ JPanel mainPanel = new JPanel(new BorderLayout());
+ mainPanel.add(textArea, BorderLayout.CENTER);
+ JPanel buttonPanel = new JPanel(new FlowLayout());
+ buttonPanel.add(testButton);
+ buttonPanel.add(passButton);
+ buttonPanel.add(failButton);
+ mainPanel.add(buttonPanel, BorderLayout.SOUTH);
+ dialog.add(mainPanel);
+ dialog.pack();
+ dialog.setVisible(true);
+ }
+
+
+}
--- a/jdk/test/javax/swing/SwingUtilities/TestBadBreak/TestBadBreak.java Tue Nov 17 10:29:28 2015 -0800
+++ b/jdk/test/javax/swing/SwingUtilities/TestBadBreak/TestBadBreak.java Tue Nov 17 13:09:16 2015 -0800
@@ -36,10 +36,10 @@
/**
* @test
- * @bug 8015085
+ * @bug 8015085 8079253
* @summary Shortening via " ... " is broken for Strings containing a combining
* diaeresis.
- * @author Sergey Bylokhov
+ * @run main TestBadBreak
*/
public class TestBadBreak {
@@ -79,6 +79,7 @@
g2d.dispose();
}
};
+ label.setOpaque(true);
frame.getContentPane().add(label);
frame.setBounds(200, 200, 200, 90);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/awt/shell/ShellFolderMemoryLeak.java Tue Nov 17 13:09:16 2015 -0800
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2015, 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 8030099
+ * @summary Memory usage of java process increases
+ after calling Win32ShellFolder:listFiles
+ multiple times on some directory with
+ large number of files/folders
+ * @modules java.desktop/sun.awt
+ * @requires (os.family == "windows")
+ * @run main/timeout=1000 ShellFolderMemoryLeak
+ */
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import sun.awt.shell.ShellFolder;
+
+public class ShellFolderMemoryLeak {
+
+ private final static String tempDir = System.getProperty("java.io.tmpdir");
+ private static Process process;
+ public static void main(String[] args) throws Exception {
+ if (args.length == 0) {
+ boolean testResultParallel
+ = createChildProcessWithParallelCollector();
+ String result = "";
+ if (!testResultParallel) {
+ result = "Test failed with Parallel collector";
+ }
+ boolean testResultDefault
+ = createChildProcessWithDefaultCollector();
+ if (!testResultDefault && !testResultParallel) {
+ result += " and with default collector both.";
+ } else if (!testResultDefault) {
+ result = "Test failed with default collector";
+ }
+ if (!"".equals(result)) {
+ throw new RuntimeException(result);
+ }
+ } else {
+ testListFile(args[args.length - 1]);
+ }
+ }
+
+ public static boolean createChildProcessWithDefaultCollector()
+ throws Exception {
+ String testDirectory = "TestDirectory1";
+ testDirectory = tempDir + testDirectory +File.separator;
+ createTestData(testDirectory);
+ return runProcess("", testDirectory);
+ }
+
+ public static boolean createChildProcessWithParallelCollector()
+ throws Exception {
+ String testDirectory = "TestDirectory2";
+ testDirectory = tempDir + testDirectory +File.separator;
+ createTestData(testDirectory);
+ return runProcess(" -XX:+UseParallelGC", testDirectory);
+ }
+
+ public static boolean runProcess(String arg1, String arg2) throws Exception {
+ String javaPath = System.getProperty("java.home");
+ String classPathDir = System.getProperty("java.class.path");
+
+ //creating java process which run same class with different Xmx value
+ String command = javaPath + File.separator + "bin" + File.separator
+ + "java -Xmx256M" + arg1 + " -cp "
+ + classPathDir
+ + " ShellFolderMemoryLeak " + arg2;
+ process = Runtime.getRuntime().exec(command);
+ BufferedReader input = null;
+ InputStream errorStream = null;
+ String line = null;
+ try {
+ int exitVal = process.waitFor();
+ input = new BufferedReader(new InputStreamReader(
+ process.getInputStream()));
+ while ((line = input.readLine()) != null) {
+ }
+ errorStream = process.getErrorStream();
+ if (checkExceptions(errorStream) || exitVal != 0) {
+ return false;
+ }
+ } catch (IllegalThreadStateException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (input != null) {
+ input.close();
+ }
+ if (errorStream != null) {
+ errorStream.close();
+ }
+ process.destroy();
+ }
+ return true;
+ }
+
+ public static boolean checkExceptions(InputStream in) throws IOException {
+ String tempString;
+ int count = in.available();
+ boolean exception = false;
+ while (count > 0) {
+ byte[] b = new byte[count];
+ in.read(b);
+ tempString = new String(b);
+ if (!exception) {
+ exception = tempString.contains("RunTimeException");
+ }
+ count = in.available();
+ }
+ return exception;
+ }
+
+ private static void createTestData(String testDirectory) {
+ String folder = "folder_";
+ File testFolder = new File(testDirectory);
+ if (testFolder.exists()) {
+ clearTestData(testDirectory);
+ } else {
+ if (testFolder.mkdir()) {
+ for (int inx = 0; inx < 100; inx++) {
+ new File(testFolder + File.separator + folder + inx).mkdir();
+ }
+ } else {
+ throw new RuntimeException("Failed to create testDirectory");
+ }
+ }
+ }
+
+ public static void deleteDirectory(File file)
+ throws IOException {
+
+ if (file.isDirectory()) {
+ if (file.list().length == 0) {
+ file.delete();
+ } else {
+ String files[] = file.list();
+ for (String temp : files) {
+ File fileDelete = new File(file, temp);
+ deleteDirectory(fileDelete);
+ }
+ if (file.list().length == 0) {
+ file.delete();
+ }
+ }
+ }
+ }
+
+ private static void testListFile(String testDirectory) {
+ try {
+ int mb = 1024 * 1024;
+ ShellFolder folder = ShellFolder.getShellFolder(
+ new File(testDirectory));
+ Runtime instance = Runtime.getRuntime();
+
+ //Memory used before calling listFiles
+ long startmem = instance.totalMemory() - instance.freeMemory();
+ long start = System.currentTimeMillis();
+ long endmem = 0;
+
+ //Calling listFiles for 5 minutes with sleep of 10 ms.
+ while ((System.currentTimeMillis() - start) < 300000) {
+ try {
+ folder.listFiles();
+ Thread.sleep(10);
+ endmem = instance.totalMemory() - instance.freeMemory();
+ } catch (InterruptedException ex) {
+ Logger.getLogger(ShellFolderMemoryLeak.class.getName())
+ .log(Level.SEVERE, "InterruptedException", ex);
+ }
+ }
+
+ //Total increase in memory after 5 minutes
+ long result = (endmem - startmem) / mb;
+
+ if (result > 100) {
+ clearTestData(testDirectory);
+ throw new RuntimeException("Test Failed");
+ }
+ clearTestData(testDirectory);
+ } catch (FileNotFoundException ex) {
+ if(process != null && process.isAlive()) {
+ process.destroy();
+ }
+ Logger.getLogger(ShellFolderMemoryLeak.class.getName())
+ .log(Level.SEVERE, "File Not Found Exception", ex);
+ }
+ }
+
+ private static void clearTestData(String testDirectory) {
+ File testFolder = new File(testDirectory);
+ try {
+ deleteDirectory(testFolder);
+ } catch (IOException ex) {
+ Logger.getLogger(ShellFolderMemoryLeak.class.getName())
+ .log(Level.SEVERE, "Unable to delete files", ex);
+ }
+ }
+}
\ No newline at end of file