From 8bb28e28a61af89e17d73ce5b1cdad196f3444c0 Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Tue, 10 Sep 2013 18:40:13 +0400 Subject: [PATCH] Cocoa does not like activities while transition in full screen is happening. This fix prevents simultaneous entering in the full screen mode. --- .../ui/mac/MacMainFrameDecorator.java | 86 ++++++++++++++----- 1 file changed, 64 insertions(+), 22 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java b/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java index aa9f64a65a13..8fd02cec4b25 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java @@ -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 myFullscreenQueue = new FullscreenQueue(); + + private class FullscreenQueue { + + private boolean waitingForAppKit = false; + private LinkedList queueModel = new LinkedList(); + + 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); - } + } + }); } + }