# HG changeset patch # User pchelko # Date 1395320338 -14400 # Node ID 2044c9d2b681f088b95fd8c17d1ef46635b41711 # Parent e05b2a687849cc4e6e9d16781a72052d7fff8dae 8037840: [macosx] Rewrite CWarning window to eliminate the ExecutorService Reviewed-by: anthony, serb diff -r e05b2a687849 -r 2044c9d2b681 jdk/src/macosx/classes/sun/lwawt/macosx/CWarningWindow.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CWarningWindow.java Thu Mar 20 12:10:53 2014 +0400 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CWarningWindow.java Thu Mar 20 16:58:58 2014 +0400 @@ -27,7 +27,6 @@ import sun.awt.AWTAccessor; import sun.awt.IconInfo; -import sun.awt.SunToolkit; import sun.java2d.SunGraphics2D; import sun.java2d.SurfaceData; import sun.java2d.opengl.CGLLayer; @@ -39,17 +38,11 @@ import java.awt.event.MouseEvent; import java.awt.geom.Point2D; import java.lang.ref.WeakReference; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; public final class CWarningWindow extends CPlatformWindow implements SecurityWarningWindow, PlatformEventNotifier { - private static class Lock {}; + private static class Lock {} private final Lock lock = new Lock(); private final static int SHOWING_DELAY = 300; @@ -97,7 +90,7 @@ public CWarningWindow(final Window _ownerWindow, final LWWindowPeer _ownerPeer) { super(); - this.ownerPeer = new WeakReference(_ownerPeer); + this.ownerPeer = new WeakReference<>(_ownerPeer); this.ownerWindow = _ownerWindow; initialize(null, null, _ownerPeer.getPlatformWindow()); @@ -122,16 +115,8 @@ } public void setVisible(boolean visible, boolean doSchedule) { - synchronized (scheduler) { - if (showingTaskHandle != null) { - showingTaskHandle.cancel(false); - showingTaskHandle = null; - } - - if (hidingTaskHandle != null) { - hidingTaskHandle.cancel(false); - hidingTaskHandle = null; - } + synchronized (taskLock) { + cancelTasks(); if (visible) { if (isVisible()) { @@ -140,20 +125,18 @@ currentIcon = 2; } - showingTaskHandle = scheduler.schedule(showingTask, 50, - TimeUnit.MILLISECONDS); - + showHideTask = new ShowingTask(); + LWCToolkit.performOnMainThreadAfterDelay(showHideTask, 50); } else { if (!isVisible()) { return; } + showHideTask = new HidingTask(); if (doSchedule) { - hidingTaskHandle = scheduler.schedule(hidingTask, HIDING_DELAY, - TimeUnit.MILLISECONDS); + LWCToolkit.performOnMainThreadAfterDelay(showHideTask, HIDING_DELAY); } else { - hidingTaskHandle = scheduler.schedule(hidingTask, 50, - TimeUnit.MILLISECONDS); + LWCToolkit.performOnMainThreadAfterDelay(showHideTask, 50); } } } @@ -325,13 +308,19 @@ @Override public void dispose() { - AccessController.doPrivileged((PrivilegedAction) () -> { - scheduler.shutdown(); - return null; - }); + cancelTasks(); super.dispose(); } + private void cancelTasks() { + synchronized (taskLock) { + if (showHideTask != null) { + showHideTask.cancel(); + showHideTask = null; + } + } + } + private void updateIconSize() { int newSize = -1; @@ -364,7 +353,7 @@ } } - private final Graphics getGraphics() { + private Graphics getGraphics() { SurfaceData sd = contentView.getSurfaceData(); if (ownerWindow == null || sd == null) { return null; @@ -409,44 +398,59 @@ return getSecurityIconInfo(currentSize, currentIcon); } - private final Runnable hidingTask = new Runnable() { - public void run() { + private final Lock taskLock = new Lock(); + private CancelableRunnable showHideTask; + + private static abstract class CancelableRunnable implements Runnable { + private volatile boolean perform = true; + + public final void cancel() { + perform = false; + } + + @Override + public final void run() { + if (perform) { + perform(); + } + } + + public abstract void perform(); + } + + private class HidingTask extends CancelableRunnable { + @Override + public void perform() { synchronized (lock) { setVisible(false); } - synchronized (scheduler) { - hidingTaskHandle = null; + synchronized (taskLock) { + showHideTask = null; } } - }; + } - private final Runnable showingTask = new Runnable() { - public void run() { + private class ShowingTask extends CancelableRunnable { + @Override + public void perform() { synchronized (lock) { if (!isVisible()) { setVisible(true); } - repaint(); } - synchronized (scheduler) { + synchronized (taskLock) { if (currentIcon > 0) { currentIcon--; - showingTaskHandle = scheduler.schedule(showingTask, SHOWING_DELAY, - TimeUnit.MILLISECONDS); + showHideTask = new ShowingTask(); + LWCToolkit.performOnMainThreadAfterDelay(showHideTask, SHOWING_DELAY); } else { - showingTaskHandle = null; + showHideTask = null; } } } - }; - - private final ScheduledExecutorService scheduler = - Executors.newSingleThreadScheduledExecutor(); - - private ScheduledFuture hidingTaskHandle; - private ScheduledFuture showingTaskHandle; + } } diff -r e05b2a687849 -r 2044c9d2b681 jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Mar 20 12:10:53 2014 +0400 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Mar 20 16:58:58 2014 +0400 @@ -47,7 +47,6 @@ import sun.lwawt.*; import sun.lwawt.LWWindowPeer.PeerType; import sun.security.action.GetBooleanAction; -import sun.awt.image.MultiResolutionImage; import sun.util.CoreResourceBundleControl; @@ -671,6 +670,13 @@ throw new InvocationTargetException(eventException); } + /** + * Schedules a {@code Runnable} execution on the Appkit thread after a delay + * @param r a {@code Runnable} to execute + * @param delay a delay in milliseconds + */ + native static void performOnMainThreadAfterDelay(Runnable r, long delay); + // This exists purely to get around permissions issues with getSystemEventQueueImpl EventQueue getSystemEventQueueForInvokeAndWait() { return getSystemEventQueueImpl(); diff -r e05b2a687849 -r 2044c9d2b681 jdk/src/macosx/native/sun/awt/LWCToolkit.m --- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m Thu Mar 20 12:10:53 2014 +0400 +++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m Thu Mar 20 16:58:58 2014 +0400 @@ -82,6 +82,39 @@ @end +@interface JavaRunnable : NSObject { } +@property jobject runnable; +- (id)initWithRunnable:(jobject)gRunnable; +- (void)perform; +@end + +@implementation JavaRunnable +@synthesize runnable = _runnable; + +- (id)initWithRunnable:(jobject)gRunnable { + if (self = [super init]) { + self.runnable = gRunnable; + } + return self; +} + +- (void)dealloc { + JNIEnv *env = [ThreadUtilities getJNIEnv]; + if (self.runnable) { + (*env)->DeleteGlobalRef(env, self.runnable); + } + [super dealloc]; +} + +- (void)perform { + JNIEnv* env = [ThreadUtilities getJNIEnv]; + static JNF_CLASS_CACHE(sjc_Runnable, "java/lang/Runnable"); + static JNF_MEMBER_CACHE(jm_Runnable_run, sjc_Runnable, "run", "()V"); + JNFCallVoidMethod(env, self.runnable, jm_Runnable_run); + [self release]; +} +@end + /* * Class: sun_lwawt_macosx_LWCToolkit * Method: nativeSyncQueue @@ -359,6 +392,25 @@ /* * Class: sun_lwawt_macosx_LWCToolkit + * Method: performOnMainThreadAfterDelay + * Signature: (Ljava/lang/Runnable;J)V + */ +JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_performOnMainThreadAfterDelay +(JNIEnv *env, jclass clz, jobject runnable, jlong delay) +{ +JNF_COCOA_ENTER(env); + jobject gRunnable = (*env)->NewGlobalRef(env, runnable); + CHECK_NULL(gRunnable); + [ThreadUtilities performOnMainThreadWaiting:NO block:^() { + JavaRunnable* performer = [[JavaRunnable alloc] initWithRunnable:gRunnable]; + [performer performSelector:@selector(perform) withObject:nil afterDelay:(delay/1000.0)]; + }]; +JNF_COCOA_EXIT(env); +} + + +/* + * Class: sun_lwawt_macosx_LWCToolkit * Method: isCapsLockOn * Signature: ()Z */ @@ -433,4 +485,3 @@ { } -