Skip to content

Commit 428cad1

Browse files
committed
Add support for OpenJDK and Java 11.
Squash port of sampottinger:java11 on processing train with a number of sub-changes, resolving processing/processing#5750 in the processing4 train. Original message below. Moves to OpenJDK11 as part of #5750. There's lots in here so a quick rundown of the bigger stuff... **Primary required changes:** Some changes directly support OpenJFX / OpenJDK 11: - Response to image loading changes caused by [JEP 320](https://openjdk.java.net/jeps/320) - Use of jmodules as necessitated by [JEP 261](https://openjdk.java.net/jeps/261) - Reponse to largely changed file paths caused by [JEP 220](https://openjdk.java.net/jeps/220). - Modifications in build system related to AdoptOpenJDK and Java 11 which have a different naming structure for downloads. - Allowing use of non-Oracle Java within internal Processing checks. **Secondary required changes:** There were some secondary required changes that impacted the usability of Processing after having moved to OpenJFX / OpenJDK 11: - Removal of com.apple.eawt calls related to [JEP 272](http://openjdk.java.net/jeps/272) - Response to HiDPI support on Windows and Linux in [JEP 263](https://openjdk.java.net/jeps/263) - Removal of `java.ext.dirs`. Would be forced by [JEP 220](http://openjdk.java.net/jeps/220). - Due to bugs on Windows, updated the JNA jars. - Changes in downloader build tasks to support AdoptOpenJDK and OpenJFX. - Updated org.eclipse.* / equinox jars. - Some optimization around size of distribution. - Update of AppBundler. - Some changes in formulation of classpath and modifications in PreprocessingService given [JEP 261](https://openjdk.java.net/jeps/261). **Incidental changes:** This was (ahem) a bit of a larger PR with the above modifications. So, I wanted to introduce automated tests when possible and convenient along with a few changes for platform sustainability in order to support development: - Addition of cross-building capability (!) made possible by AdoptOpenJDK. - Addition of mockito for testing. - Upgrade of junit. - Addition of ant-contrib. - Standardized nomenclature around JRE / JDK in `build/build.xml` - Deduplication of code in `jre/build.xml`. - Addition of JavaDoc in a few places. - Some refactoring of PImage / Shape to support increased testing and readability in image manipulation code.
1 parent a429baa commit 428cad1

File tree

126 files changed

+7325
-1690
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

126 files changed

+7325
-1690
lines changed

.classpath

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<classpath>
3+
<classpathentry kind="src" path="src"/>
4+
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
5+
<attributes>
6+
<attribute name="module" value="true"/>
7+
</attributes>
8+
</classpathentry>
9+
<classpathentry kind="lib" path="library/jogl-all.jar"/>
10+
<classpathentry kind="lib" path="library/gluegen-rt.jar"/>
11+
<classpathentry kind="lib" path="apple.jar"/>
12+
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/JavaFX11"/>
13+
<classpathentry kind="output" path="bin"/>
14+
</classpath>

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.DS_Store
22
.AppleDouble
3+
*.iml
34
._*
45
*~
56
/build/shared/reference.zip

app/build.xml

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
<fail unless="core-built" message="Please build the core library first and make sure it is located at ../core/library/core.jar" />
1414

1515
<mkdir dir="bin" />
16-
16+
1717
<!-- copy languages files -->
1818
<copy todir="bin">
1919
<fileset dir="src">
2020
<include name="processing/app/languages/*.properties" />
2121
</fileset>
2222
</copy>
23-
23+
2424
<!-- in some cases, pde.jar was not getting built
2525
https://github.com/processing/processing/issues/1792 -->
2626
<delete file="pde.jar" />
@@ -30,22 +30,19 @@
3030

3131
<javac source="1.8"
3232
target="1.8"
33-
destdir="bin"
34-
excludes="**/tools/format/**"
35-
encoding="UTF-8"
36-
includeAntRuntime="false"
37-
classpath="../core/library/core.jar;
38-
../core/apple.jar;
39-
lib/ant.jar;
40-
lib/ant-launcher.jar;
33+
destdir="bin"
34+
excludes="**/tools/format/**"
35+
encoding="UTF-8"
36+
includeAntRuntime="false"
37+
classpath="../core/library/core.jar;
38+
../core/apple.jar;
39+
lib/ant.jar;
40+
lib/ant-launcher.jar;
4141
lib/jna.jar;
4242
lib/jna-platform.jar"
4343
debug="on"
44-
nowarn="true"
45-
compiler="org.eclipse.jdt.core.JDTCompilerAdapter">
44+
nowarn="true">
4645
<src path="src" />
47-
<compilerclasspath path="../java/mode/org.eclipse.jdt.core.jar;
48-
../java/mode/jdtCompilerAdapter.jar" />
4946
</javac>
5047
</target>
5148

app/lib/jna

2.41 MB
Binary file not shown.

app/lib/jna-platform.jar

667 KB
Binary file not shown.

app/lib/jna.jar

387 KB
Binary file not shown.

app/src/processing/app/Platform.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,10 +339,10 @@ static public File getJavaHome() {
339339
File[] plugins = getContentFile("../PlugIns").listFiles(new FilenameFilter() {
340340
public boolean accept(File dir, String name) {
341341
return dir.isDirectory() &&
342-
name.endsWith(".jdk") && !name.startsWith(".");
342+
name.contains("jdk") && !name.startsWith(".");
343343
}
344344
});
345-
return new File(plugins[0], "Contents/Home/jre");
345+
return new File(plugins[0], "Contents/Home");
346346
}
347347
// On all other platforms, it's the 'java' folder adjacent to Processing
348348
return getContentFile("java");
@@ -412,4 +412,4 @@ static public int unsetenv(String variable) {
412412
static public int getSystemDPI() {
413413
return inst.getSystemDPI();
414414
}
415-
}
415+
}

app/src/processing/app/platform/LinuxPlatform.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,6 @@ public class LinuxPlatform extends DefaultPlatform {
4040
public void initBase(Base base) {
4141
super.initBase(base);
4242

43-
String javaVendor = System.getProperty("java.vendor");
44-
String javaVM = System.getProperty("java.vm.name");
45-
if (javaVendor == null ||
46-
(!javaVendor.contains("Sun") && !javaVendor.contains("Oracle")) ||
47-
javaVM == null || !javaVM.contains("Java")) {
48-
Messages.showWarning("Not fond of this Java VM",
49-
"Processing requires Java 8 from Oracle.\n" +
50-
"Other versions such as OpenJDK, IcedTea,\n" +
51-
"and GCJ are strongly discouraged. Among other things, you're\n" +
52-
"likely to run into problems with sketch window size and\n" +
53-
"placement. For more background, please read the wiki:\n" +
54-
"https://github.com/processing/processing/wiki/Supported-Platforms#linux", null);
55-
}
56-
5743
// Set x11 WM_CLASS property which is used as the application
5844
// name by Gnome3 and other window managers.
5945
// https://github.com/processing/processing/issues/2534

app/src/processing/app/platform/ThinkDifferent.java

Lines changed: 75 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,15 @@
2424

2525
import java.awt.event.*;
2626
import java.io.File;
27+
import java.lang.reflect.InvocationHandler;
28+
import java.lang.reflect.InvocationTargetException;
29+
import java.lang.reflect.Method;
30+
import java.lang.reflect.Proxy;
31+
import java.util.List;
2732

2833
import javax.swing.*;
2934

30-
import com.apple.eawt.*;
31-
import com.apple.eawt.AppEvent.*;
35+
import com.apple.eawt.Application;
3236

3337
import processing.app.*;
3438
import processing.app.ui.About;
@@ -65,44 +69,40 @@ static protected void init(final Base base) {
6569
if (adapter == null) {
6670
adapter = new ThinkDifferent(); //base);
6771
}
68-
69-
application.setAboutHandler(new AboutHandler() {
70-
public void handleAbout(AboutEvent ae) {
71-
new About(null);
72-
}
72+
73+
setHandler(application, "setAboutHandler", (proxy, method, args) -> {
74+
new About(null);
75+
return null;
7376
});
74-
75-
application.setPreferencesHandler(new PreferencesHandler() {
76-
public void handlePreferences(PreferencesEvent arg0) {
77-
base.handlePrefs();
78-
}
77+
78+
setHandler(application, "setPreferencesHandler", (proxy, method, args) -> {
79+
base.handlePrefs();
80+
return null;
7981
});
8082

81-
application.setOpenFileHandler(new OpenFilesHandler() {
82-
public void openFiles(OpenFilesEvent event) {
83-
for (File file : event.getFiles()) {
84-
base.handleOpen(file.getAbsolutePath());
85-
}
83+
setHandler(application, "setOpenFileHandler", (proxy, method, args) -> {
84+
Method m = args[0].getClass().getMethod("getFiles");
85+
for (File file : (List<File>) m.invoke(args[0])) {
86+
base.handleOpen(file.getAbsolutePath());
8687
}
88+
return null;
8789
});
88-
89-
application.setPrintFileHandler(new PrintFilesHandler() {
90-
public void printFiles(PrintFilesEvent event) {
91-
// TODO not yet implemented
92-
}
90+
91+
setHandler(application, "setPrintFileHandler", (proxy, method, args) -> {
92+
// TODO not yet implemented
93+
return null;
9394
});
94-
95-
application.setQuitHandler(new QuitHandler() {
96-
public void handleQuitRequestWith(QuitEvent event, QuitResponse response) {
97-
if (base.handleQuit()) {
98-
response.performQuit();
99-
} else {
100-
response.cancelQuit();
101-
}
95+
96+
setHandler(application, "setQuitHandler", (proxy, method, args) -> {
97+
if (base.handleQuit()) {
98+
args[1].getClass().getMethod("performQuit").invoke(args[1]);
99+
} else {
100+
args[1].getClass().getMethod("cancelQuit").invoke(args[1]);
102101
}
102+
return null;
103103
});
104104

105-
// Set the menubar to be used when nothing else is open.
105+
// Set the menubar to be used when nothing else is open.
106106
JMenuBar defaultMenuBar = new JMenuBar();
107107
JMenu fileMenu = buildFileMenu(base);
108108
defaultMenuBar.add(fileMenu);
@@ -117,12 +117,12 @@ public void handleQuitRequestWith(QuitEvent event, QuitResponse response) {
117117
e.printStackTrace(); // oh well, never mind
118118
}
119119
// } else {
120-
// // The douchebags at Oracle didn't feel that a working f*king menubar
121-
// // on OS X was important enough to make it into the 7u40 release.
120+
// // The douchebags at Oracle didn't feel that a working f*king menubar
121+
// // on OS X was important enough to make it into the 7u40 release.
122122
// //http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8007267
123123
// // It languished in the JDK 8 source and has been backported for 7u60:
124124
// //http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8022667
125-
//
125+
//
126126
// JFrame offscreen = new JFrame();
127127
// offscreen.setUndecorated(true);
128128
// offscreen.setJMenuBar(defaultMenuBar);
@@ -131,12 +131,51 @@ public void handleQuitRequestWith(QuitEvent event, QuitResponse response) {
131131
// offscreen.setVisible(true);
132132
// }
133133
}
134-
134+
135135

136136
// public ThinkDifferent(Base base) {
137137
// this.base = base;
138138
// }
139139

140+
/**
141+
* Sets a handler on an instance of {@link Application}, taking into account JVM version
142+
* differences.
143+
*
144+
* @param app an instance of {@link Application}
145+
* @param name the "set handler" method name
146+
* @param handler the handler
147+
*/
148+
private static void setHandler(Application app, String name, InvocationHandler handler) {
149+
// Determine which version of com.apple.eawt.Application to use and pass it a handler of the
150+
// appropriate type
151+
Method[] methods = app.getClass().getMethods();
152+
for (Method m : methods) {
153+
if (!name.equals(m.getName())) {
154+
continue;
155+
}
156+
if (m.getParameterCount() != 1) {
157+
continue;
158+
}
159+
Class paramType = m.getParameterTypes()[0];
160+
try {
161+
// Allow a null handler
162+
Object proxy = null;
163+
if (handler != null) {
164+
proxy = Proxy.newProxyInstance(
165+
paramType.getClassLoader(), new Class<?>[] { paramType }, handler);
166+
}
167+
m.invoke(app, proxy);
168+
} catch (IllegalArgumentException ex) {
169+
// TODO: Print error?: method doesn't take an interface, etc.
170+
} catch (IllegalAccessException ex) {
171+
// TODO: Print error?: Other method invocation problem
172+
} catch (InvocationTargetException ex) {
173+
ex.getCause().printStackTrace();
174+
// TODO: Print ex.getCause() a different way?
175+
}
176+
break;
177+
}
178+
}
140179

141180
/**
142181
* Gimpy file menu to be used on OS X when no sketches are open.
@@ -162,7 +201,7 @@ public void actionPerformed(ActionEvent e) {
162201
fileMenu.add(item);
163202

164203
item = Toolkit.newJMenuItemShift(Language.text("menu.file.sketchbook"), 'K');
165-
item.addActionListener(new ActionListener() {
204+
item.addActionListener(new ActionListener() {
166205
@Override
167206
public void actionPerformed(ActionEvent e) {
168207
base.getNextMode().showSketchbookFrame();

app/src/processing/app/platform/WindowsPlatform.java

Lines changed: 8 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,16 @@ public class WindowsPlatform extends DefaultPlatform {
6464
"\\" + APP_NAME.toLowerCase() + ".exe \"%1\"";
6565
static final String REG_DOC = APP_NAME + ".Document";
6666

67+
// Starting with Java 9, the scaling is done automatically. If DPI is
68+
// used to scaling within the application, one ends up with 2x the
69+
// expected scale. See JEP 263.
70+
private static final int WINDOWS_NATIVE_DPI = 96;
6771

6872
public void initBase(Base base) {
6973
super.initBase(base);
74+
7075
checkAssociations();
76+
7177
//checkQuickTime();
7278
checkPath();
7379

@@ -627,56 +633,9 @@ public int unsetenv(String variable) {
627633
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
628634

629635

630-
// Need to extend com.sun.jna.platform.win32.User32 to access
631-
// Win32 function GetDpiForSystem()
632-
interface ExtUser32 extends StdCallLibrary, com.sun.jna.platform.win32.User32 {
633-
ExtUser32 INSTANCE = (ExtUser32) Native.loadLibrary("user32", ExtUser32.class, W32APIOptions.DEFAULT_OPTIONS);
634-
635-
public int GetDpiForSystem();
636-
637-
public int SetProcessDpiAwareness(int value);
638-
639-
public final int DPI_AWARENESS_INVALID = -1;
640-
public final int DPI_AWARENESS_UNAWARE = 0;
641-
public final int DPI_AWARENESS_SYSTEM_AWARE = 1;
642-
public final int DPI_AWARENESS_PER_MONITOR_AWARE = 2;
643-
644-
public Pointer SetThreadDpiAwarenessContext(Pointer dpiContext);
645-
646-
public final Pointer DPI_AWARENESS_CONTEXT_UNAWARE = new Pointer(-1);
647-
public final Pointer DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = new Pointer(-2);
648-
public final Pointer DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = new Pointer(-3);
649-
}
650-
651-
652-
static private int detected = detectSystemDPI();
653-
654-
655636
public int getSystemDPI() {
656-
if (detected == -1) {
657-
return super.getSystemDPI();
658-
}
659-
return detected;
637+
// Note that this is supported "natively" within Java - See JEP 263.
638+
return WINDOWS_NATIVE_DPI;
660639
}
661640

662-
663-
public static int detectSystemDPI() {
664-
try {
665-
ExtUser32.INSTANCE.SetProcessDpiAwareness(ExtUser32.DPI_AWARENESS_SYSTEM_AWARE);
666-
} catch (Throwable e) {
667-
// Ignore error
668-
}
669-
try {
670-
ExtUser32.INSTANCE.SetThreadDpiAwarenessContext(ExtUser32.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
671-
} catch (Throwable e) {
672-
// Ignore error (call valid only on Windows 10)
673-
}
674-
try {
675-
return ExtUser32.INSTANCE.GetDpiForSystem();
676-
} catch (Throwable e) {
677-
// DPI detection failed, fall back with default
678-
System.out.println("DPI detection failed, fallback to 96 dpi");
679-
return -1;
680-
}
681-
}
682641
}

0 commit comments

Comments
 (0)