apache / netbeans

Apache NetBeans
https://netbeans.apache.org/
Apache License 2.0
2.65k stars 850 forks source link

Mac OS "Open With" does not open the files #4005

Open mbastian opened 2 years ago

mbastian commented 2 years ago

Description

On Mac OS, Netbeans does not support opening files by double clicking or right clicking (Open With). Also, terminal commands like open foo.java -a /Applications/NetBeans/Apache\ NetBeans\ 13.app/ would open Netbeans but the file itself once started.

As there has been work recently on a native Swift launcher I wonder if that would make it easier to implement this one.

Thank you!

Use case/motivation

Opening files from Finder would make Netbeans more convenient to use.

Related issues

I know this was discussed previously but I couldn't locate a recent GH issue about it.

Are you willing to submit a PR?

Code of Conduct

oyarzun commented 2 years ago

@mbastian I looked into this and I do not believe it is possible with the current implementation. I think we would need to change the macOS Native launcher to use libjvm.dylib rather than just executing the unix shell script launcher. This is what the Windows launcher does. Such a change would probably require a discussion on the dev mailing list.

cc @neilcsmith-net @mcdonnell-john

neilcsmith-net commented 2 years ago

@oyarzun do you know where info on handling Open As events in Swift is? I wonder if the launcher can handle the event and pass to the shell script? Directly running the Swift launcher inside the App bundle with the file as an argument works as expected.

oyarzun commented 2 years ago

@neilcsmith-net it is handled by the AppDelegate in a NSApplication, but console applications do not have an app delegate.

https://developer.apple.com/documentation/appkit/nsapplicationdelegate https://developer.apple.com/documentation/appkit/nsapplicationdelegate/2887193-application

This allows "open with" to work, but add an extra icon in the dock.

diff --git a/nb/ide.launcher/macosx/Sources/NetBeansLauncher/main.swift b/nb/ide.launcher/macosx/Sources/NetBeansLauncher/main.swift
index 923952ae1a..3c8b23cce7 100644
--- a/nb/ide.launcher/macosx/Sources/NetBeansLauncher/main.swift
+++ b/nb/ide.launcher/macosx/Sources/NetBeansLauncher/main.swift
@@ -18,21 +18,66 @@
 */

 import Foundation
+import AppKit

-let netbeansURL = Bundle.main.url(forResource: "netbeans", withExtension: "", subdirectory: "NetBeans/netbeans/bin")
+var openArgs = [String]()
+
+func launchNB() {
+    let launchNetbeans = Process()
+    launchNetbeans.arguments = args
+    launchNetbeans.executableURL = netbeansURL
+    do {
+        try launchNetbeans.run()
+    }
+    catch {
+        NSLog("NetBeans failed to start")
+    }
+
+    // needed to keep Dock name based on CFBundleName from Info.plist
+    // does not work if called from command line.
+    launchNetbeans.waitUntilExit()
+}
+
+class AppDelegate: NSObject, NSApplicationDelegate {
+    func application(_ application: NSApplication, open urls: [URL]) {
+        for url in urls {
+            args.append(url.path)
+            NSLog("urls %@", url.path)
+        }
+    }
+
+    func application(_ sender: NSApplication, openFile filename: String) -> Bool {
+        args.append(filename)
+        NSLog("openFile %@", filename)
+        return true
+    }
+
+    func application(_ sender: NSApplication, openFiles filenames: [String]) {
+        for filename in filenames {
+            args.append(filename)
+            NSLog("openFiles %@", filename)
+        }
+    }
+
+    func applicationDidFinishLaunching(_ notification: Notification) {
+        launchNB()
+    }
+}

 var args = [String]()
+let app = NSApplication.shared
+let delegate = AppDelegate()
+app.delegate = delegate
+
+
+let netbeansURL = Bundle.main.url(forResource: "netbeans", withExtension: "", subdirectory: "NetBeans/netbeans/bin")
+

 // add user's command line arguments
 for argument in Array(CommandLine.arguments.dropFirst()) {
     args.append(argument)
 }

-let launchNetbeans = Process()
-launchNetbeans.arguments = args
-launchNetbeans.executableURL = netbeansURL
-try launchNetbeans.run()

-// needed to keep Dock name based on CFBundleName from Info.plist
-// does not work if called from command line.
-launchNetbeans.waitUntilExit()
+app.run()
+
neilcsmith-net commented 2 years ago

it is handled by the AppDelegate in a NSApplication, but console applications do not have an app delegate.

Thanks. That was what I was looking for. I realise the difference with console applications, although is the Swift launcher calling the shell script also the reason the open files listener in applemenu is not working?

Is blocking the run loop with waitUntilExit a good idea?

oyarzun commented 2 years ago

Is blocking the run loop with waitUntilExit a good idea?

It was the only way I could figure out to get the dock icon to not be called "java". But it does not work In the above diff.

Thanks. That was what I was looking for. I realise the difference with console applications, although is the Swift launcher calling the shell script also the reason the open files listener in applemenu is not working?

Maybe... Although, I just replaced the Swift launcher with a symlink to the bash script in the app bundle (the way it used to be), and the "Open with" does not work either. I'll do some debugging to see if there might be a solution via the applemenu.