mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[ui] macOS frame decorator cleanup
- dropping pre-10.7 code - moving custom URL handler to a more appropriate place GitOrigin-RevId: f066884c0ed288c614fcc17a30d67def936a2373
This commit is contained in:
committed by
intellij-monorepo-bot
parent
46b8dbe4c2
commit
f69d7123ce
@@ -10,7 +10,6 @@ import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.ui.ComponentUtil;
|
||||
import com.intellij.ui.ScreenUtil;
|
||||
import com.intellij.ui.mac.MacMainFrameDecorator;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -48,7 +47,7 @@ public abstract class IdeFrameDecorator implements IdeFrameImpl.FrameDecorator {
|
||||
public static IdeFrameDecorator decorate(@NotNull JFrame frame, @NotNull Disposable parentDisposable) {
|
||||
try {
|
||||
if (SystemInfo.isMac) {
|
||||
return new MacMainFrameDecorator(frame, PlatformUtils.isAppCode(), parentDisposable);
|
||||
return new MacMainFrameDecorator(frame, parentDisposable);
|
||||
}
|
||||
else if (SystemInfo.isWindows) {
|
||||
return new WinMainFrameDecorator(frame);
|
||||
@@ -191,4 +190,4 @@ public abstract class IdeFrameDecorator implements IdeFrameImpl.FrameDecorator {
|
||||
public static boolean isCustomDecorationActive() {
|
||||
return SystemInfo.isWindows && Registry.is("ide.win.frame.decoration") && JdkEx.isCustomDecorationSupported();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,25 +3,15 @@ package com.intellij.ui.mac;
|
||||
|
||||
import com.apple.eawt.*;
|
||||
import com.intellij.ide.ActiveWindowsWatcher;
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.ide.ui.UISettingsListener;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.BuildNumber;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.wm.impl.IdeFrameDecorator;
|
||||
import com.intellij.openapi.wm.impl.IdeRootPane;
|
||||
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.ui.UIUtil;
|
||||
import com.sun.jna.Callback;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.concurrency.AsyncPromise;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
@@ -32,62 +22,49 @@ import java.awt.*;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.EventListener;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.intellij.ui.mac.foundation.Foundation.invoke;
|
||||
|
||||
public final class MacMainFrameDecorator extends IdeFrameDecorator {
|
||||
private static final Logger LOG = Logger.getInstance(MacMainFrameDecorator.class);
|
||||
|
||||
private final FullscreenQueue<Runnable> myFullscreenQueue = new FullscreenQueue<>();
|
||||
|
||||
private final EventDispatcher<FSListener> myDispatcher = EventDispatcher.create(FSListener.class);
|
||||
|
||||
private interface FSListener extends FullScreenListener, EventListener {}
|
||||
private static class FSAdapter extends FullScreenAdapter implements FSListener {}
|
||||
|
||||
private static class FullscreenQueue <T extends Runnable> {
|
||||
private boolean waitingForAppKit = false;
|
||||
private final LinkedList<Runnable> queueModel = new LinkedList<>();
|
||||
private static class FullScreenQueue {
|
||||
private final LinkedList<Runnable> myQueue = new LinkedList<>();
|
||||
private boolean myWaitingForAppKit = false;
|
||||
|
||||
synchronized void runOrEnqueue(@NotNull T runnable) {
|
||||
if (waitingForAppKit) {
|
||||
enqueue(runnable);
|
||||
synchronized void runOrEnqueue(Runnable runnable) {
|
||||
if (myWaitingForAppKit) {
|
||||
myQueue.add(runnable);
|
||||
}
|
||||
else {
|
||||
ApplicationManager.getApplication().invokeLater(runnable);
|
||||
waitingForAppKit = true;
|
||||
myWaitingForAppKit = 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;
|
||||
synchronized void runFromQueue() {
|
||||
if (!myQueue.isEmpty()) {
|
||||
myQueue.remove().run();
|
||||
myWaitingForAppKit = true;
|
||||
}
|
||||
else {
|
||||
myWaitingForAppKit = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void enterFullscreen() {
|
||||
private void enterFullScreen() {
|
||||
myInFullScreen = true;
|
||||
storeFullScreenStateIfNeeded();
|
||||
myFullscreenQueue.runFromQueue();
|
||||
myFullScreenQueue.runFromQueue();
|
||||
}
|
||||
|
||||
private void exitFullscreen() {
|
||||
private void exitFullScreen() {
|
||||
myInFullScreen = false;
|
||||
storeFullScreenStateIfNeeded();
|
||||
|
||||
JRootPane rootPane = myFrame.getRootPane();
|
||||
if (rootPane != null) rootPane.putClientProperty(FULL_SCREEN, null);
|
||||
myFullscreenQueue.runFromQueue();
|
||||
myFullScreenQueue.runFromQueue();
|
||||
}
|
||||
|
||||
private void storeFullScreenStateIfNeeded() {
|
||||
@@ -96,7 +73,6 @@ public final class MacMainFrameDecorator extends IdeFrameDecorator {
|
||||
}
|
||||
|
||||
public static final String FULL_SCREEN = "Idea.Is.In.FullScreen.Mode.Now";
|
||||
private static boolean HAS_FULLSCREEN_UTILITIES;
|
||||
|
||||
private static Method requestToggleFullScreenMethod;
|
||||
private static Method enterFullScreenMethod;
|
||||
@@ -104,211 +80,89 @@ public final class MacMainFrameDecorator extends IdeFrameDecorator {
|
||||
|
||||
static {
|
||||
try {
|
||||
//noinspection SpellCheckingInspection
|
||||
Class.forName("com.apple.eawt.FullScreenUtilities");
|
||||
//noinspection JavaReflectionMemberAccess
|
||||
enterFullScreenMethod = Application.class.getMethod("requestEnterFullScreen", Window.class);
|
||||
leaveFullScreenMethod = Application.class.getMethod("requestLeaveFullScreen", Window.class);
|
||||
HAS_FULLSCREEN_UTILITIES = true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
HAS_FULLSCREEN_UTILITIES = false;
|
||||
}
|
||||
// temporary solution for the old Runtime
|
||||
if (!HAS_FULLSCREEN_UTILITIES) {
|
||||
try {
|
||||
Class.forName("com.apple.eawt.FullScreenUtilities");
|
||||
//noinspection JavaReflectionMemberAccess
|
||||
enterFullScreenMethod = Application.class.getMethod("requestEnterFullScreen", Window.class);
|
||||
//noinspection JavaReflectionMemberAccess
|
||||
leaveFullScreenMethod = Application.class.getMethod("requestLeaveFullScreen", Window.class);
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
// temporary solution for the old runtime
|
||||
//noinspection JavaReflectionMemberAccess
|
||||
requestToggleFullScreenMethod = Application.class.getMethod("requestToggleFullScreen", Window.class);
|
||||
HAS_FULLSCREEN_UTILITIES = true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
HAS_FULLSCREEN_UTILITIES = false;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
Logger.getInstance(MacMainFrameDecorator.class).debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final boolean FULL_SCREEN_AVAILABLE = HAS_FULLSCREEN_UTILITIES;
|
||||
|
||||
private static boolean SHOWN = false;
|
||||
|
||||
private static final Callback SET_VISIBLE_CALLBACK = new Callback() {
|
||||
@SuppressWarnings("unused")
|
||||
public void callback(ID caller, ID selector, ID value) {
|
||||
SHOWN = value.intValue() == 1;
|
||||
SwingUtilities.invokeLater(CURRENT_SETTER);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Callback IS_VISIBLE = new Callback() {
|
||||
@SuppressWarnings("unused")
|
||||
public boolean callback(ID caller) {
|
||||
return SHOWN;
|
||||
}
|
||||
};
|
||||
|
||||
private static final AtomicInteger UNIQUE_COUNTER = new AtomicInteger(0);
|
||||
|
||||
public static final Runnable TOOLBAR_SETTER = () -> {
|
||||
final UISettings settings = UISettings.getInstance();
|
||||
settings.setShowMainToolbar(SHOWN);
|
||||
settings.fireUISettingsChanged();
|
||||
};
|
||||
|
||||
public static final Runnable NAVBAR_SETTER = () -> {
|
||||
final UISettings settings = UISettings.getInstance();
|
||||
settings.setShowNavigationBar(SHOWN);
|
||||
settings.fireUISettingsChanged();
|
||||
};
|
||||
|
||||
public static final Supplier<Boolean> NAV_BAR_GETTER = () -> UISettings.getInstance().getShowNavigationBar();
|
||||
|
||||
public static final Supplier<Boolean> TOOLBAR_GETTER = () -> UISettings.getInstance().getShowMainToolbar();
|
||||
|
||||
private static Runnable CURRENT_SETTER = null;
|
||||
private static Supplier<Boolean> CURRENT_GETTER = null;
|
||||
private static CustomProtocolHandler ourProtocolHandler = null;
|
||||
|
||||
private final FullScreenQueue myFullScreenQueue = new FullScreenQueue();
|
||||
private final EventDispatcher<FSListener> myDispatcher = EventDispatcher.create(FSListener.class);
|
||||
private boolean myInFullScreen;
|
||||
|
||||
public MacMainFrameDecorator(@NotNull JFrame frame, boolean navBar, @NotNull Disposable parentDisposable) {
|
||||
public MacMainFrameDecorator(@NotNull JFrame frame, @NotNull Disposable parentDisposable) {
|
||||
super(frame);
|
||||
|
||||
if (CURRENT_SETTER == null) {
|
||||
//noinspection AssignmentToStaticFieldFromInstanceMethod
|
||||
CURRENT_SETTER = navBar ? NAVBAR_SETTER : TOOLBAR_SETTER;
|
||||
//noinspection AssignmentToStaticFieldFromInstanceMethod
|
||||
CURRENT_GETTER = navBar ? NAV_BAR_GETTER : TOOLBAR_GETTER;
|
||||
//noinspection AssignmentToStaticFieldFromInstanceMethod
|
||||
SHOWN = CURRENT_GETTER.get();
|
||||
}
|
||||
if (leaveFullScreenMethod != null || requestToggleFullScreenMethod != null) {
|
||||
FullScreenUtilities.setWindowCanFullScreen(frame, true);
|
||||
|
||||
//noinspection Convert2Lambda
|
||||
ApplicationManager.getApplication().getMessageBus().connect(parentDisposable).subscribe(UISettingsListener.TOPIC, new UISettingsListener() {
|
||||
@Override
|
||||
public void uiSettingsChanged(@NotNull UISettings uiSettings) {
|
||||
if (CURRENT_GETTER != null) {
|
||||
//noinspection AssignmentToStaticFieldFromInstanceMethod
|
||||
SHOWN = CURRENT_GETTER.get();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final ID pool = invoke("NSAutoreleasePool", "new");
|
||||
|
||||
int v = UNIQUE_COUNTER.incrementAndGet();
|
||||
|
||||
try {
|
||||
if (SystemInfo.isMacOSLion) {
|
||||
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);
|
||||
}
|
||||
|
||||
@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 windowEnteringFullScreen(AppEvent.FullScreenEvent event) {
|
||||
JRootPane rootPane = frame.getRootPane();
|
||||
if (rootPane != null && rootPane.getBorder() != null && Registry.is("ide.mac.transparentTitleBarAppearance")) {
|
||||
rootPane.setBorder(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowEnteredFullScreen(AppEvent.FullScreenEvent event) {
|
||||
// We can get the notification when the frame has been disposed
|
||||
JRootPane rootPane = frame.getRootPane();
|
||||
if (rootPane != null) rootPane.putClientProperty(FULL_SCREEN, Boolean.TRUE);
|
||||
enterFullscreen();
|
||||
myFrame.validate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowExitedFullScreen(AppEvent.FullScreenEvent event) {
|
||||
// We can get the notification when the frame has been disposed
|
||||
if (myFrame == null/* || ORACLE_BUG_ID_8003173*/) return;
|
||||
JRootPane rootPane = frame.getRootPane();
|
||||
if (rootPane instanceof IdeRootPane && Registry.is("ide.mac.transparentTitleBarAppearance")) {
|
||||
IdeRootPane ideRootPane = (IdeRootPane)rootPane;
|
||||
UIUtil.setCustomTitleBar(frame, ideRootPane, runnable -> {
|
||||
Disposer.register(parentDisposable, () -> runnable.run());
|
||||
});
|
||||
}
|
||||
exitFullscreen();
|
||||
ActiveWindowsWatcher.addActiveWindow(frame);
|
||||
myFrame.validate();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
final ID window = MacUtil.findWindowForTitle(frame.getTitle());
|
||||
if (window == null) return;
|
||||
|
||||
// toggle toolbar
|
||||
String className = "IdeaToolbar" + v;
|
||||
final ID ownToolbar = Foundation.allocateObjcClassPair(Foundation.getObjcClass("NSToolbar"), className);
|
||||
Foundation.registerObjcClassPair(ownToolbar);
|
||||
|
||||
final ID toolbar = invoke(invoke(className, "alloc"), "initWithIdentifier:", Foundation.nsString(className));
|
||||
Foundation.cfRetain(toolbar);
|
||||
|
||||
invoke(toolbar, "setVisible:", 0); // hide native toolbar by default
|
||||
|
||||
Foundation.addMethod(ownToolbar, Foundation.createSelector("setVisible:"), SET_VISIBLE_CALLBACK, "v*");
|
||||
Foundation.addMethod(ownToolbar, Foundation.createSelector("isVisible"), IS_VISIBLE, "B*");
|
||||
|
||||
Foundation.executeOnMainThread(true, true, () -> {
|
||||
invoke(window, "setToolbar:", toolbar);
|
||||
invoke(window, "setShowsToolbarButton:", 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
finally {
|
||||
invoke(pool, "release");
|
||||
}
|
||||
|
||||
// extract to static method for exclude this from OpenURIHandler() {} anonymous class
|
||||
createProtocolHandler();
|
||||
}
|
||||
|
||||
private static void createProtocolHandler() {
|
||||
if (ourProtocolHandler == null) {
|
||||
// install uri handler
|
||||
final ID mainBundle = invoke("NSBundle", "mainBundle");
|
||||
final ID urlTypes = invoke(mainBundle, "objectForInfoDictionaryKey:", Foundation.nsString("CFBundleURLTypes"));
|
||||
final BuildNumber build = ApplicationInfoImpl.getShadowInstance().getBuild();
|
||||
if (urlTypes.equals(ID.NIL) && build != null && !build.isSnapshot()) {
|
||||
LOG.warn("no url bundle present. \n" +
|
||||
"To use platform protocol handler to open external links specify required protocols in the mac app layout section of the build file\n" +
|
||||
"Example: args.urlSchemes = [\"your-protocol\"] will handle following links: your-protocol://open?file=file&line=line");
|
||||
return;
|
||||
}
|
||||
ourProtocolHandler = new CustomProtocolHandler();
|
||||
Application.getApplication().setOpenURIHandler(new OpenURIHandler() {
|
||||
// Native full screen listener can be set only once
|
||||
FullScreenUtilities.addFullScreenListenerTo(frame, new FullScreenListener() {
|
||||
@Override
|
||||
public void openURI(AppEvent.OpenURIEvent event) {
|
||||
ourProtocolHandler.openLink(event.getURI());
|
||||
public void windowEnteringFullScreen(AppEvent.FullScreenEvent event) {
|
||||
myDispatcher.getMulticaster().windowEnteringFullScreen(event);
|
||||
}
|
||||
|
||||
@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 windowEnteringFullScreen(AppEvent.FullScreenEvent event) {
|
||||
JRootPane rootPane = myFrame.getRootPane();
|
||||
if (rootPane != null && rootPane.getBorder() != null && Registry.is("ide.mac.transparentTitleBarAppearance")) {
|
||||
rootPane.setBorder(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowEnteredFullScreen(AppEvent.FullScreenEvent event) {
|
||||
// We can get the notification when the frame has been disposed
|
||||
JRootPane rootPane = myFrame.getRootPane();
|
||||
if (rootPane != null) rootPane.putClientProperty(FULL_SCREEN, Boolean.TRUE);
|
||||
enterFullScreen();
|
||||
myFrame.validate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowExitedFullScreen(AppEvent.FullScreenEvent event) {
|
||||
// We can get the notification when the frame has been disposed
|
||||
JRootPane rootPane = myFrame.getRootPane();
|
||||
if (rootPane instanceof IdeRootPane && Registry.is("ide.mac.transparentTitleBarAppearance")) {
|
||||
IdeRootPane ideRootPane = (IdeRootPane)rootPane;
|
||||
UIUtil.setCustomTitleBar(myFrame, ideRootPane, runnable -> {
|
||||
Disposer.register(parentDisposable, () -> runnable.run());
|
||||
});
|
||||
}
|
||||
exitFullScreen();
|
||||
ActiveWindowsWatcher.addActiveWindow(myFrame);
|
||||
myFrame.validate();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -322,9 +176,6 @@ public final class MacMainFrameDecorator extends IdeFrameDecorator {
|
||||
@NotNull
|
||||
@Override
|
||||
public Promise<Boolean> toggleFullScreen(boolean state) {
|
||||
if (!SystemInfo.isMacOSLion || myFrame == null) {
|
||||
return Promises.rejectedPromise();
|
||||
}
|
||||
if (myInFullScreen == state) {
|
||||
return Promises.resolvedPromise(state);
|
||||
}
|
||||
@@ -344,40 +195,26 @@ public final class MacMainFrameDecorator extends IdeFrameDecorator {
|
||||
}
|
||||
});
|
||||
|
||||
// temporary solution for the old Runtime
|
||||
if (enterFullScreenMethod == null || leaveFullScreenMethod == null) {
|
||||
myFullscreenQueue.runOrEnqueue(this::toggleFullScreenNow);
|
||||
} else {
|
||||
myFullscreenQueue.runOrEnqueue(state ? this::enterFullScreenNow : this::leaveFullScreenNow);
|
||||
// temporary solution for the old runtime
|
||||
if (requestToggleFullScreenMethod != null) {
|
||||
myFullScreenQueue.runOrEnqueue(() -> invokeAppMethod(requestToggleFullScreenMethod));
|
||||
}
|
||||
else if (state) {
|
||||
myFullScreenQueue.runOrEnqueue(() -> invokeAppMethod(enterFullScreenMethod));
|
||||
}
|
||||
else {
|
||||
myFullScreenQueue.runOrEnqueue(() -> invokeAppMethod(leaveFullScreenMethod));
|
||||
}
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
public void toggleFullScreenNow() {
|
||||
private void invokeAppMethod(Method method) {
|
||||
try {
|
||||
requestToggleFullScreenMethod.invoke(Application.getApplication(), myFrame);
|
||||
method.invoke(Application.getApplication(), myFrame);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.warn(e);
|
||||
Logger.getInstance(MacMainFrameDecorator.class).warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void enterFullScreenNow() {
|
||||
try {
|
||||
enterFullScreenMethod.invoke(Application.getApplication(), myFrame);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void leaveFullScreenNow() {
|
||||
try {
|
||||
leaveFullScreenMethod.invoke(Application.getApplication(), myFrame);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.ui.mac;
|
||||
|
||||
import com.apple.eawt.AppEvent;
|
||||
import com.apple.eawt.Application;
|
||||
import com.apple.eawt.OpenURIHandler;
|
||||
import com.intellij.diagnostic.LoadingState;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.actions.AboutAction;
|
||||
@@ -13,12 +15,15 @@ import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.TransactionGuard;
|
||||
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.util.BuildNumber;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.ui.CustomProtocolHandler;
|
||||
import com.intellij.ui.mac.foundation.Foundation;
|
||||
import com.intellij.ui.mac.foundation.ID;
|
||||
import com.sun.jna.Callback;
|
||||
@@ -91,6 +96,7 @@ public final class MacOSApplicationProvider {
|
||||
|
||||
if (JnaLoader.isLoaded()) {
|
||||
installAutoUpdateMenu();
|
||||
installProtocolHandler();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,5 +175,27 @@ public final class MacOSApplicationProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void installProtocolHandler() {
|
||||
ID mainBundle = Foundation.invoke("NSBundle", "mainBundle");
|
||||
ID urlTypes = Foundation.invoke(mainBundle, "objectForInfoDictionaryKey:", Foundation.nsString("CFBundleURLTypes"));
|
||||
if (!urlTypes.equals(ID.NIL)) {
|
||||
CustomProtocolHandler handler = new CustomProtocolHandler();
|
||||
Application.getApplication().setOpenURIHandler(new OpenURIHandler() {
|
||||
@Override
|
||||
public void openURI(AppEvent.OpenURIEvent event) {
|
||||
handler.openLink(event.getURI());
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
BuildNumber build = ApplicationInfoImpl.getShadowInstance().getBuild();
|
||||
if (!(build == null || build.isSnapshot())) {
|
||||
LOG.warn("No URL bundle (CFBundleURLTypes) is defined in the main bundle.\n" +
|
||||
"To be able to open external links, specify protocols in the app layout section of the build file.\n" +
|
||||
"Example: args.urlSchemes = [\"your-protocol\"] will handle following links: your-protocol://open?file=file&line=line");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user