Cocoa does not like activities while transition in full screen is happening. This fix prevents simultaneous entering in the full screen mode.

This commit is contained in:
Denis Fokin
2013-09-10 18:41:11 +04:00
parent c837b30b81
commit 8bb28e28a6
@@ -21,6 +21,7 @@ import com.intellij.ide.ui.UISettings;
import com.intellij.ide.ui.UISettingsListener;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.application.impl.LaterInvocator;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.BuildNumber;
import com.intellij.openapi.util.SystemInfo;
@@ -41,6 +42,7 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;
import static com.intellij.ui.mac.foundation.Foundation.invoke;
@@ -52,28 +54,60 @@ public class MacMainFrameDecorator extends IdeFrameDecorator implements UISettin
private static final Logger LOG = Logger.getInstance("#com.intellij.ui.mac.MacMainFrameDecorator");
private final static boolean ORACLE_BUG_ID_8003173 = SystemInfo.isJavaVersionAtLeast("1.7");
private final FullscreenQueue<Runnable> myFullscreenQueue = new FullscreenQueue<Runnable>();
private class FullscreenQueue <T extends Runnable> {
private boolean waitingForAppKit = false;
private LinkedList<Runnable> queueModel = new LinkedList<Runnable>();
synchronized void runOrEnqueue (final T runnable) {
if (waitingForAppKit) {
enqueue(runnable);
} else {
LaterInvocator.invokeLater(runnable);
waitingForAppKit = true;
}
}
synchronized private void enqueue (final T runnable) {
queueModel.add(runnable);
}
synchronized void runFromQueue () {
if (!queueModel.isEmpty()) {
queueModel.remove().run();
waitingForAppKit = true;
} else {
waitingForAppKit = false;
}
}
}
// Fullscreen listener delivers event too late,
// so we use method swizzling here
private final Callback windowWillEnterFullScreenCallBack = new Callback() {
public void callback(ID self,
ID nsNotification)
{
enterFullscreen();
invoke(self, "oldWindowWillEnterFullScreen:", nsNotification);
enterFullscreen();
}
};
private void enterFullscreen() {
myInFullScreen = true;
myFrame.storeFullScreenStateIfNeeded(true);
myFullscreenQueue.runFromQueue();
}
private final Callback windowWillExitFullScreenCallBack = new Callback() {
public void callback(ID self,
ID nsNotification)
{
exitFullscreen();
invoke(self, "oldWindowWillExitFullScreen:", nsNotification);
exitFullscreen();
}
};
@@ -83,6 +117,7 @@ public class MacMainFrameDecorator extends IdeFrameDecorator implements UISettin
JRootPane rootPane = myFrame.getRootPane();
if (rootPane != null) rootPane.putClientProperty(FULL_SCREEN, null);
myFullscreenQueue.runFromQueue();
}
public static final String FULL_SCREEN = "Idea.Is.In.FullScreen.Mode.Now";
@@ -292,27 +327,34 @@ public class MacMainFrameDecorator extends IdeFrameDecorator implements UISettin
}
@Override
public void toggleFullScreen(boolean state) {
public void toggleFullScreen(final boolean state) {
if (!SystemInfo.isMacOSLion || myFrame == null) return;
if (SystemInfo.isJavaVersionAtLeast("1.7")) {
try {
requestToggleFullScreenMethod.invoke(Application.getApplication(),myFrame);
}
catch (IllegalAccessException e) {
LOG.error(e);
}
catch (InvocationTargetException e) {
LOG.error(e);
}
} else if (myInFullScreen != state) {
final ID window = MacUtil.findWindowForTitle(myFrame.getTitle());
if (window == null) return;
Foundation.executeOnMainThread(new Runnable() {
@Override
public void run() {
invoke(window, "toggleFullScreen:", window);
myFullscreenQueue.runOrEnqueue( new Runnable() {
@Override
public void run() {
if (SystemInfo.isJavaVersionAtLeast("1.7")) {
try {
requestToggleFullScreenMethod.invoke(Application.getApplication(),myFrame);
}
catch (IllegalAccessException e) {
LOG.error(e);
}
catch (InvocationTargetException e) {
LOG.error(e);
}
} else if (myInFullScreen != state) {
final ID window = MacUtil.findWindowForTitle(myFrame.getTitle());
if (window == null) return;
Foundation.executeOnMainThread(new Runnable() {
@Override
public void run() {
invoke(window, "toggleFullScreen:", window);
}
}, true, true);
}
}, true, true);
}
}
});
}
}