diff --git a/platform/platform-impl/src/com/intellij/ide/actions/TogglePresentationModeAction.java b/platform/platform-impl/src/com/intellij/ide/actions/TogglePresentationModeAction.java index 565b78f040f7..f0ffd671de36 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/TogglePresentationModeAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/TogglePresentationModeAction.java @@ -27,6 +27,7 @@ import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ex.ToolWindowManagerEx; import com.intellij.openapi.wm.impl.DesktopLayout; @@ -52,15 +53,16 @@ public class TogglePresentationModeAction extends AnAction implements DumbAware @Override public void actionPerformed(AnActionEvent e){ - UISettings settings = UISettings.getInstance(); - Project project = e.getProject(); + final UISettings settings = UISettings.getInstance(); + final Project project = e.getProject(); settings.PRESENTATION_MODE = !settings.PRESENTATION_MODE; - if (project != null) { + if (settings.PRESENTATION_MODE && project != null) { hideToolWindows(project); } + settings.fireUISettingsChanged(); UIDefaults defaults = UIManager.getDefaults(); @@ -84,6 +86,7 @@ public class TogglePresentationModeAction extends AnAction implements DumbAware oldFonts.clear(); } + ActionCallback callback = ActionCallback.DONE; if (project != null) { Window window = IdeFrameImpl.getActiveFrame(); if (window instanceof IdeFrameImpl) { @@ -91,27 +94,35 @@ public class TogglePresentationModeAction extends AnAction implements DumbAware final PropertiesComponent propertiesComponent = PropertiesComponent.getInstance(project); if (settings.PRESENTATION_MODE) { propertiesComponent.setValue("full.screen.before.presentation.mode", String.valueOf(frame.isInFullScreen())); - frame.toggleFullScreen(true); + callback = frame.toggleFullScreen(true); } else { if (frame.isInFullScreen()) { final String value = propertiesComponent.getValue("full.screen.before.presentation.mode"); - frame.toggleFullScreen("true".equalsIgnoreCase(value)); + callback = frame.toggleFullScreen("true".equalsIgnoreCase(value)); } } } } + callback.doWhenProcessed(new Runnable() { + @Override + public void run() { + int fontSize = settings.PRESENTATION_MODE + ? settings.PRESENTATION_MODE_FONT_SIZE + : EditorColorsManager.getInstance().getGlobalScheme().getEditorFontSize(); + for (Editor editor : EditorFactory.getInstance().getAllEditors()) { + if (editor instanceof EditorEx) { + ((EditorEx)editor).setFontSize(fontSize); + } + } + UISettings.getInstance().fireUISettingsChanged(); + LafManager.getInstance().updateUI(); + EditorUtil.reinitSettings(); - int fontSize = settings.PRESENTATION_MODE - ? settings.PRESENTATION_MODE_FONT_SIZE - : EditorColorsManager.getInstance().getGlobalScheme().getEditorFontSize(); - for (Editor editor : EditorFactory.getInstance().getAllEditors()) { - if (editor instanceof EditorEx) { - ((EditorEx)editor).setFontSize(fontSize); + if (!settings.PRESENTATION_MODE && project != null) { + hideToolWindows(project); + } } - } - UISettings.getInstance().fireUISettingsChanged(); - LafManager.getInstance().updateUI(); - EditorUtil.reinitSettings(); + }); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFrameEx.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFrameEx.java index 4d03be7e4aa4..166502df621b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFrameEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFrameEx.java @@ -15,10 +15,13 @@ */ package com.intellij.openapi.wm.ex; +import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.wm.IdeFrame; +import org.jetbrains.annotations.NotNull; public interface IdeFrameEx extends IdeFrame { boolean isInFullScreen(); - void toggleFullScreen(boolean state); + @NotNull + ActionCallback toggleFullScreen(boolean state); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameDecorator.java index 2af026e25c88..1a06b43a80ff 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameDecorator.java @@ -16,6 +16,7 @@ package com.intellij.openapi.wm.impl; import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.ScreenUtil; import com.intellij.ui.mac.MacMainFrameDecorator; @@ -36,7 +37,7 @@ public abstract class IdeFrameDecorator implements Disposable { public abstract boolean isInFullScreen(); - public abstract void toggleFullScreen(boolean state); + public abstract ActionCallback toggleFullScreen(boolean state); @Override public void dispose() { @@ -83,11 +84,11 @@ public abstract class IdeFrameDecorator implements Disposable { } @Override - public void toggleFullScreen(boolean state) { - if (myFrame == null) return; + public ActionCallback toggleFullScreen(boolean state) { + if (myFrame == null) return ActionCallback.REJECTED; GraphicsDevice device = ScreenUtil.getScreenDevice(myFrame.getBounds()); - if (device == null) return; + if (device == null) return ActionCallback.REJECTED; try { myFrame.getRootPane().putClientProperty(ScreenUtil.DISPOSE_TEMPORARY, Boolean.TRUE); @@ -112,6 +113,7 @@ public abstract class IdeFrameDecorator implements Disposable { notifyFrameComponents(state); } + return ActionCallback.DONE; } } @@ -138,11 +140,12 @@ public abstract class IdeFrameDecorator implements Disposable { } @Override - public void toggleFullScreen(boolean state) { + public ActionCallback toggleFullScreen(boolean state) { if (myFrame != null) { myRequestedState = state; X11UiUtil.toggleFullScreenMode(myFrame); } + return ActionCallback.DONE; } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java index eaa1e63977c5..33e0a84f68a8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java @@ -37,6 +37,7 @@ import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.SystemInfo; @@ -539,15 +540,17 @@ public class IdeFrameImpl extends JFrame implements IdeFrameEx, DataProvider { return myFrameDecorator != null && myFrameDecorator.isInFullScreen(); } + @NotNull @Override - public void toggleFullScreen(boolean state) { + public ActionCallback toggleFullScreen(boolean state) { if (myFrameDecorator != null) { - myFrameDecorator.toggleFullScreen(state); + return myFrameDecorator.toggleFullScreen(state); } IdeFrame[] frames = WindowManager.getInstance().getAllProjectFrames(); for (IdeFrame frame : frames) { ((IdeFrameImpl)frame).updateBorder(); } + return ActionCallback.DONE; } @Override 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 110286994817..64d904de69ca 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java @@ -23,6 +23,7 @@ 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.ActionCallback; import com.intellij.openapi.util.BuildNumber; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.wm.impl.IdeFrameDecorator; @@ -31,6 +32,7 @@ import com.intellij.ui.CustomProtocolHandler; import com.intellij.ui.mac.foundation.Foundation; import com.intellij.ui.mac.foundation.ID; import com.intellij.ui.mac.foundation.MacUtil; +import com.intellij.util.EventDispatcher; import com.intellij.util.Function; import com.sun.jna.Callback; import com.sun.jna.Pointer; @@ -42,6 +44,7 @@ import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.EventListener; import java.util.LinkedList; import java.util.concurrent.atomic.AtomicInteger; @@ -56,7 +59,12 @@ public class MacMainFrameDecorator extends IdeFrameDecorator implements UISettin private final FullscreenQueue myFullscreenQueue = new FullscreenQueue(); - private class FullscreenQueue { + private final EventDispatcher myDispatcher = EventDispatcher.create(FSListener.class); + + private interface FSListener extends FullScreenListener, EventListener {} + private static class FSAdapter extends FullScreenAdapter implements FSListener {} + + private static class FullscreenQueue { private boolean waitingForAppKit = false; private LinkedList queueModel = new LinkedList(); @@ -225,8 +233,29 @@ public class MacMainFrameDecorator extends IdeFrameDecorator implements UISettin if (!FULL_SCREEN_AVAILABLE) return; FullScreenUtilities.setWindowCanFullScreen(frame, true); + // Native fullscreen listener can be set only once + FullScreenUtilities.addFullScreenListenerTo(frame, new FullScreenListener() { + @Override + public void windowEnteringFullScreen(AppEvent.FullScreenEvent event) { + myDispatcher.getMulticaster().windowEnteringFullScreen(event); + } - FullScreenUtilities.addFullScreenListenerTo(frame, new FullScreenAdapter() { + @Override + public void windowEnteredFullScreen(AppEvent.FullScreenEvent event) { + myDispatcher.getMulticaster().windowEnteredFullScreen(event); + } + + @Override + public void windowExitingFullScreen(AppEvent.FullScreenEvent event) { + myDispatcher.getMulticaster().windowExitingFullScreen(event); + } + + @Override + public void windowExitedFullScreen(AppEvent.FullScreenEvent event) { + myDispatcher.getMulticaster().windowExitedFullScreen(event); + } + }); + myDispatcher.addListener(new FSAdapter() { @Override public void windowEnteredFullScreen(AppEvent.FullScreenEvent event) { // We can get the notification when the frame has been disposed @@ -328,13 +357,27 @@ public class MacMainFrameDecorator extends IdeFrameDecorator implements UISettin } @Override - public void toggleFullScreen(final boolean state) { - if (!SystemInfo.isMacOSLion || myFrame == null || myInFullScreen == state) return; + public ActionCallback toggleFullScreen(final boolean state) { + if (!SystemInfo.isMacOSLion || myFrame == null || myInFullScreen == state) return ActionCallback.REJECTED; + final ActionCallback callback = new ActionCallback(); + myDispatcher.addListener(new FSAdapter() { + @Override + public void windowExitedFullScreen(AppEvent.FullScreenEvent event) { + callback.setDone(); + myDispatcher.removeListener(this); + } + + @Override + public void windowEnteredFullScreen(AppEvent.FullScreenEvent event) { + callback.setDone(); + myDispatcher.removeListener(this); + } + }); myFullscreenQueue.runOrEnqueue( new Runnable() { @Override public void run() { - try { + try { requestToggleFullScreenMethod.invoke(Application.getApplication(),myFrame); } catch (IllegalAccessException e) { @@ -345,6 +388,7 @@ public class MacMainFrameDecorator extends IdeFrameDecorator implements UISettin } } }); + return callback; } }