Skip to content

Commit

Permalink
Migrate deprecated com.apple.eawt calls in core.
Browse files Browse the repository at this point in the history
As part of #5753 / #5750, remove deprecated com.apple.eawt calls made in the core module. Specifically, respond to (JEP 272)[http://openjdk.java.net/jeps/272] which is generating warnings on sketch run and may cause failure in future JDKs.
  • Loading branch information
sampottinger committed Jan 18, 2019
1 parent 99002c7 commit f68fd9e
Showing 1 changed file with 53 additions and 69 deletions.
122 changes: 53 additions & 69 deletions core/src/processing/core/ThinkDifferent.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,115 +22,99 @@

package processing.core;

import java.awt.Image;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.apple.eawt.Application;
import java.awt.*;


/**
* Deal with issues related to thinking differently.
* Deal with issues related to Mac OS window behavior.
*
* We have to register a quit handler to safely shut down the sketch,
* otherwise OS X will just kill the sketch when a user hits Cmd-Q.
* In addition, we have a method to set the dock icon image so we look more
* like a native application.
* like a native desktop.
*
* This is a stripped-down version of what's in processing.app.platform to fix
* <a href="https://github.com/processing/processing/issues/3301">3301</a>.
*/
public class ThinkDifferent {

// http://developer.apple.com/documentation/Java/Reference/1.4.2/appledoc/api/com/apple/eawt/Application.html
private static Application application;
private static Desktop desktop;
private static Taskbar taskbar;

// True if user has tried to quit once. Prevents us from canceling the quit
// call if the sketch is held up for some reason, like an exception that's
// managed to put the sketch in a bad state.
static boolean attemptedQuit;


/**
* Initialize the sketch with the quit handler.
*
* Initialize the sketch with the quit handler such that, if there is no known
* crash, the application will not exit on its own if this is the first quit
* attempt.
*
* @param sketch The sketch whose quit handler callback should be set.
*/
static public void init(final PApplet sketch) {
if (application == null) {
application = Application.getApplication();
}

setHandler(application, "setQuitHandler", (proxy, method, args) -> {
getDesktop().setQuitHandler((event, quitResponse) -> {

This comment has been minimized.

Copy link
@ssilverman

ssilverman Jan 19, 2019

This lambda won't compile to the correct package for all JDK's 1.8+. (That is, unless source is always compiled when using Processing; that's the condition to make it so this works across all JDK's 1.8+.) As a test, compile this on JDK 11 with "source 1.8" and "target 1.8" and then try to run on JDK 1.8. Same for the reverse. Compile with JDK 1.8 and try to run it on JDK 11.

This comment has been minimized.

Copy link
@ssilverman

ssilverman Jan 19, 2019

Unless of course JDK 1.8 support isn't required here... :)

sketch.exit();
if (PApplet.uncaughtThrowable == null && // no known crash
!attemptedQuit) { // haven't tried yet
args[1].getClass().getMethod("cancelQuit").invoke(args[1]); // tell OS X we'll handle this

boolean noKnownCrash = PApplet.uncaughtThrowable == null;

if (noKnownCrash && !attemptedQuit) { // haven't tried yet
quitResponse.cancelQuit(); // tell OS X we'll handle this
attemptedQuit = true;
} else {
args[1].getClass().getMethod("performQuit").invoke(args[1]); // just force it this time
quitResponse.performQuit(); // just force it this time
}
return null;
});
}

/**
* Sets a handler on an instance of {@link Application}, taking into account JVM version
* differences.
* Remove the quit handler.
*/
static public void cleanup() {
getDesktop().setQuitHandler(null);
}

/**
* Called via reflection from PSurfaceAWT and others, set the dock icon image.
*
* @param app an instance of {@link Application}
* @param name the "set handler" method name
* @param handler the handler
* @param image The image to provide for Processing icon.
*/
private static void setHandler(Application app, String name, InvocationHandler handler) {
// Determine which version of com.apple.eawt.Application to use and pass it a handler of the
// appropriate type
Method[] methods = app.getClass().getMethods();
for (Method m : methods) {
if (!name.equals(m.getName())) {
continue;
}
if (m.getParameterCount() != 1) {
continue;
}
Class paramType = m.getParameterTypes()[0];
try {
// Allow a null handler
Object proxy = null;
if (handler != null) {
proxy = Proxy.newProxyInstance(
paramType.getClassLoader(), new Class<?>[] { paramType }, handler);
}
m.invoke(app, proxy);
} catch (IllegalArgumentException ex) {
// TODO: Print error?: method doesn't take an interface, etc.
} catch (IllegalAccessException ex) {
// TODO: Print error?: Other method invocation problem
} catch (InvocationTargetException ex) {
ex.getCause().printStackTrace();
// TODO: Print ex.getCause() a different way?
}
break;
}
static public void setIconImage(Image image) {
getTaskbar().setIconImage(image);
}

static public void cleanup() {
if (application == null) {
application = Application.getApplication();
/**
* Get the taskbar where OS visual settings can be provided.
*
* @return Cached taskbar singleton instance.
*/
static private Taskbar getTaskbar() {
if (taskbar == null) {
taskbar = Taskbar.getTaskbar();
}
setHandler(application, "setQuitHandler", null);

return taskbar;
}

// Called via reflection from PSurfaceAWT and others
static public void setIconImage(Image image) {
// When already set, is a sun.awt.image.MultiResolutionCachedImage on OS X
// Image current = application.getDockIconImage();
// System.out.println("current dock icon image is " + current);
// System.out.println("changing to " + image);
/**
* Get the desktop where OS behavior can be provided.
*
* @return Cached desktop singleton instance.
*/
static private Desktop getDesktop() {
if (desktop == null) {
desktop = Desktop.getDesktop();
}

application.setDockIconImage(image);
return desktop;
}


// Instead, just use Application.getApplication() inside your app
// static public Application getApplication() {
// return application;
// return desktop;
// }
}

0 comments on commit f68fd9e

Please sign in to comment.