mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[mac] fullscreen bottom empty space fixed + restore frame state on start
This commit is contained in:
@@ -19,6 +19,7 @@ import com.intellij.ide.AppLifecycleListener;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.impl.ProjectUtil;
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.notification.impl.IdeNotificationArea;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.MnemonicHelper;
|
||||
@@ -69,6 +70,7 @@ import java.io.File;
|
||||
|
||||
// Made non-final for Fabrique
|
||||
public class IdeFrameImpl extends JFrame implements IdeFrame, DataProvider {
|
||||
private static final String FULL_SCREEN = "FullScreen";
|
||||
private String myTitle;
|
||||
|
||||
private String myFileTitle;
|
||||
@@ -81,6 +83,8 @@ public class IdeFrameImpl extends JFrame implements IdeFrame, DataProvider {
|
||||
private final BalloonLayout myBalloonLayout;
|
||||
private static boolean myUpdatingTitle;
|
||||
private MacMainFrameDecorator myFrameDecorator;
|
||||
|
||||
private boolean myRestoreFullscreen;
|
||||
|
||||
public IdeFrameImpl(ApplicationInfoEx applicationInfoEx, ActionManagerEx actionManager, UISettings uiSettings, DataManager dataManager,
|
||||
final Application application, final String[] commandLineArgs) {
|
||||
@@ -275,6 +279,14 @@ public class IdeFrameImpl extends JFrame implements IdeFrame, DataProvider {
|
||||
}
|
||||
|
||||
public void setProject(final Project project) {
|
||||
if (SystemInfo.isMacOSLion && myProject != project && project != null) {
|
||||
myRestoreFullscreen = myProject == null && shouldRestoreFullScreen(project);
|
||||
|
||||
if (myProject != null) {
|
||||
storeFullScreenStateIfNeeded(false); // disable for old project
|
||||
}
|
||||
}
|
||||
|
||||
myProject = project;
|
||||
if (project != null) {
|
||||
if (myRootPane != null) {
|
||||
@@ -293,6 +305,28 @@ public class IdeFrameImpl extends JFrame implements IdeFrame, DataProvider {
|
||||
if (project == null) {
|
||||
FocusTrackback.release(this);
|
||||
}
|
||||
|
||||
if (isVisible() && myRestoreFullscreen) {
|
||||
MacMainFrameDecorator.toggleFullScreen(this);
|
||||
myRestoreFullscreen = false;
|
||||
storeFullScreenStateIfNeeded(false); // reset
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean b) {
|
||||
super.setVisible(b);
|
||||
|
||||
if (b && myRestoreFullscreen) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MacMainFrameDecorator.toggleFullScreen(IdeFrameImpl.this);
|
||||
myRestoreFullscreen = false;
|
||||
storeFullScreenStateIfNeeded(false); // reset
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void installDefaultProjectStatusBarWidgets(@NotNull final Project project) {
|
||||
@@ -352,6 +386,30 @@ public class IdeFrameImpl extends JFrame implements IdeFrame, DataProvider {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public void storeFullScreenStateIfNeeded() {
|
||||
storeFullScreenStateIfNeeded(MacMainFrameDecorator.isFullScreenMode(this));
|
||||
}
|
||||
|
||||
public void storeFullScreenStateIfNeeded(boolean state) {
|
||||
if (!SystemInfo.isMacOSLion) return;
|
||||
|
||||
if (myProject != null) {
|
||||
PropertiesComponent.getInstance(myProject).setValue(FULL_SCREEN, Boolean.valueOf(state).toString());
|
||||
} else {
|
||||
//PropertiesComponent.getInstance().setValue(FULL_SCREEN, Boolean.valueOf(state).toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean shouldRestoreFullScreen(Project project) {
|
||||
if (!SystemInfo.isMacOSLion) return false;
|
||||
|
||||
if (project != null) {
|
||||
return PropertiesComponent.getInstance(project).getBoolean(FULL_SCREEN, false);
|
||||
} else {
|
||||
return false; // PropertiesComponent.getInstance().getBoolean(FULL_SCREEN, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
UIUtil.applyRenderingHints(g);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.openapi.wm.impl;
|
||||
|
||||
import com.intellij.Patches;
|
||||
import com.intellij.ide.AppLifecycleListener;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.IdeEventQueue;
|
||||
import com.intellij.ide.impl.DataManagerImpl;
|
||||
@@ -43,6 +44,7 @@ import com.intellij.ui.mac.MacMainFrameDecorator;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.sun.jna.platform.WindowUtils;
|
||||
import org.jdom.Element;
|
||||
@@ -134,7 +136,8 @@ public final class WindowManagerImpl extends WindowManagerEx implements Applicat
|
||||
public WindowManagerImpl(DataManager dataManager,
|
||||
ApplicationInfoEx applicationInfoEx,
|
||||
ActionManagerEx actionManager,
|
||||
UISettings uiSettings) {
|
||||
UISettings uiSettings,
|
||||
MessageBus bus) {
|
||||
myApplicationInfoEx = applicationInfoEx;
|
||||
myDataManager = dataManager;
|
||||
myActionManager = actionManager;
|
||||
@@ -185,6 +188,26 @@ public final class WindowManagerImpl extends WindowManagerEx implements Applicat
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bus.connect().subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() {
|
||||
@Override
|
||||
public void appClosing() {
|
||||
// save fullscreen window states
|
||||
if (SystemInfo.isMacOSLion) {
|
||||
Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
|
||||
|
||||
if (openProjects.length > 0) {
|
||||
WindowManagerEx wm = WindowManagerEx.getInstanceEx();
|
||||
for (Project project : openProjects) {
|
||||
IdeFrameImpl frame = wm.getFrame(project);
|
||||
if (frame != null) {
|
||||
frame.storeFullScreenStateIfNeeded();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showFrame(final String[] args) {
|
||||
@@ -672,7 +695,8 @@ public final class WindowManagerImpl extends WindowManagerEx implements Applicat
|
||||
|
||||
final IdeFrameImpl frame = getFrame(project);
|
||||
if (frame != null) {
|
||||
final Rectangle rectangle = frame.getBounds();
|
||||
boolean usePreviousBounds = SystemInfo.isMacOSLion && WindowManagerEx.getInstanceEx().isFullScreen(frame);
|
||||
final Rectangle rectangle = usePreviousBounds ? myFrameBounds : frame.getBounds();
|
||||
frameElement.setAttribute(X_ATTR, Integer.toString(rectangle.x));
|
||||
frameElement.setAttribute(Y_ATTR, Integer.toString(rectangle.y));
|
||||
frameElement.setAttribute(WIDTH_ATTR, Integer.toString(rectangle.width));
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.intellij.ide.ui.UISettingsListener;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.impl.IdeFrameImpl;
|
||||
import com.intellij.ui.mac.foundation.Foundation;
|
||||
import com.intellij.ui.mac.foundation.ID;
|
||||
import com.intellij.util.Function;
|
||||
@@ -90,7 +90,9 @@ public class MacMainFrameDecorator implements UISettingsListener, Disposable {
|
||||
|
||||
private static Runnable CURRENT_SETTER = null;
|
||||
private static Function<Object, Boolean> CURRENT_GETTER = null;
|
||||
private String myClassName;
|
||||
|
||||
private Callback myDidExit;
|
||||
private Callback myDidEnter;
|
||||
|
||||
public MacMainFrameDecorator(@NotNull final Frame frame, final boolean navBar) {
|
||||
final ID window = findWindowForTitle(frame.getTitle());
|
||||
@@ -106,20 +108,75 @@ public class MacMainFrameDecorator implements UISettingsListener, Disposable {
|
||||
|
||||
final ID pool = invoke("NSAutoreleasePool", "new");
|
||||
|
||||
int v = UNIQUE_COUNTER.incrementAndGet();
|
||||
|
||||
try {
|
||||
if (SystemInfo.isMacOSLion) {
|
||||
// fullscreen
|
||||
// fullscreen support
|
||||
|
||||
final ID delegateClass = Foundation.registerObjcClass(Foundation.getClass("NSObject"), "IdeaNSWindowDelegate" + v);
|
||||
Foundation.registerObjcClassPair(delegateClass);
|
||||
|
||||
myDidExit = new Callback() {
|
||||
public void callback(ID caller, ID notification) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (frame instanceof IdeFrameImpl) {
|
||||
((IdeFrameImpl)frame).storeFullScreenStateIfNeeded(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
Foundation.addMethod(delegateClass, Foundation.createSelector("windowDidExitFullScreen:"), myDidExit, "v*");
|
||||
|
||||
myDidEnter = new Callback() {
|
||||
public void callback(ID caller, ID notification) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (frame instanceof IdeFrameImpl) {
|
||||
//((IdeFrameImpl)frame).storeFullScreenStateIfNeeded(true);
|
||||
|
||||
// fix problem with bottom empty bar
|
||||
// it seems like the title is still visible in fullscreen but the window itself shifted up for titlebar height
|
||||
// and the size of the frame is still calculated to be the height of the screen which is wrong
|
||||
// so just add these titlebar height to the frame height once again
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
frame.setSize(frame.getWidth(), frame.getHeight() + frame.getInsets().top);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Foundation.addMethod(delegateClass, Foundation.createSelector("windowDidEnterFullScreen:"), myDidEnter, "v*");
|
||||
|
||||
// enable fullscreen titlebar button
|
||||
invoke(window, "setCollectionBehavior:", 1 << 7); // NSCollectionBehaviorFullScreenPrimary = 1 << 7, NSCollectionBehaviorFullScreenAuxiliary = 1 << 8
|
||||
|
||||
ID notificationCenter = invoke("NSNotificationCenter", "defaultCenter");
|
||||
|
||||
ID delegate = invoke(invoke("IdeaNSWindowDelegate" + v, "alloc"), "init");
|
||||
invoke(notificationCenter, "addObserver:selector:name:object:", delegate,
|
||||
Foundation.createSelector("windowDidEnterFullScreen:"),
|
||||
Foundation.cfString("NSWindowDidEnterFullScreenNotification"), window);
|
||||
|
||||
//invoke(notificationCenter, "addObserver:selector:name:object:", delegate,
|
||||
// Foundation.createSelector("windowDidExitFullScreen:"),
|
||||
// Foundation.cfString("NSWindowDidExitFullScreenNotification"), window);
|
||||
} else {
|
||||
// toggle toolbar
|
||||
|
||||
myClassName = "IdeaToolbar" + UNIQUE_COUNTER.incrementAndGet();
|
||||
|
||||
final ID ownToolbar = Foundation.registerObjcClass(Foundation.getClass("NSToolbar"), myClassName);
|
||||
String className = "IdeaToolbar" + v;
|
||||
final ID ownToolbar = Foundation.registerObjcClass(Foundation.getClass("NSToolbar"), className);
|
||||
Foundation.registerObjcClassPair(ownToolbar);
|
||||
|
||||
ID toolbar = invoke(invoke(myClassName, "alloc"), "initWithIdentifier:", Foundation.cfString(myClassName));
|
||||
ID toolbar = invoke(invoke(className, "alloc"), "initWithIdentifier:", Foundation.cfString(className));
|
||||
Foundation.cfRetain(toolbar);
|
||||
|
||||
invoke(toolbar, "setVisible:", 0); // hide native toolbar by default
|
||||
@@ -152,6 +209,15 @@ public class MacMainFrameDecorator implements UISettingsListener, Disposable {
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
public static void toggleFullScreen(Frame frame) {
|
||||
if (!SystemInfo.isMacOSLion) return;
|
||||
|
||||
final ID window = findWindowForTitle(frame.getTitle());
|
||||
if (window == null) return;
|
||||
|
||||
invoke(window, "toggleFullScreen:", window);
|
||||
}
|
||||
|
||||
public static boolean isFullScreenMode(@NotNull Frame frame) {
|
||||
if (!SystemInfo.isMacOSLion) return false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user