diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java index 59d241b..8d45096 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java @@ -1687,6 +1687,7 @@ public static final long /*int*/ sel_redComponent = sel_registerName("redComponent"); public static final long /*int*/ sel_redo = sel_registerName("redo"); public static final long /*int*/ sel_reflectScrolledClipView_ = sel_registerName("reflectScrolledClipView:"); +public static final long /*int*/ sel_registerAWTAppWithOptions_ = sel_registerName("registerAWTAppWithOptions:"); public static final long /*int*/ sel_registerForDraggedTypes_ = sel_registerName("registerForDraggedTypes:"); public static final long /*int*/ sel_release = sel_registerName("release"); public static final long /*int*/ sel_reload_ = sel_registerName("reload:"); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java index 7e1054a..596fa5f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java @@ -840,39 +840,45 @@ NSNumber id = new NSNumber(dictionary.objectForKey(key)); addPool(new NSAutoreleasePool(id.integerValue())); + boolean appRegistered = registerApplication(); + application = NSApplication.sharedApplication(); isEmbedded = application.isRunning(); - /* - * Feature in the Macintosh. On OS 10.2, it is necessary - * to explicitly check in with the Process Manager and set - * the current process to be the front process in order for - * windows to come to the front by default. The fix is call - * both GetCurrentProcess() and SetFrontProcess(). - * - * NOTE: It is not actually necessary to use the process - * serial number returned by GetCurrentProcess() in the - * call to SetFrontProcess() (ie. kCurrentProcess can be - * used) but both functions must be called in order for - * windows to come to the front. - */ - int [] psn = new int [2]; - if (OS.GetCurrentProcess (psn) == OS.noErr) { - int pid = OS.getpid (); - long /*int*/ ptr = getApplicationName().UTF8String(); - if (ptr != 0) OS.CPSSetProcessName (psn, ptr); - if (!isBundled ()) { - OS.TransformProcessType (psn, OS.kProcessTransformToForegroundApplication); - OS.SetFrontProcess (psn); + if (!appRegistered) { + /* + * Feature in the Macintosh. On OS 10.2, it is necessary + * to explicitly check in with the Process Manager and set + * the current process to be the front process in order for + * windows to come to the front by default. The fix is call + * both GetCurrentProcess() and SetFrontProcess(). + * + * NOTE: It is not actually necessary to use the process + * serial number returned by GetCurrentProcess() in the + * call to SetFrontProcess() (ie. kCurrentProcess can be + * used) but both functions must be called in order for + * windows to come to the front. + */ + int [] psn = new int [2]; + if (OS.GetCurrentProcess (psn) == OS.noErr) { + long /*int*/ ptr = getApplicationName().UTF8String(); + if (ptr != 0) OS.CPSSetProcessName (psn, ptr); + if (!isBundled ()) { + OS.TransformProcessType (psn, OS.kProcessTransformToForegroundApplication); + OS.SetFrontProcess (psn); + } } - ptr = OS.getenv (ascii ("APP_ICON_" + pid)); - if (ptr != 0) { - NSString path = NSString.stringWithUTF8String (ptr); - NSImage image = (NSImage) new NSImage().alloc(); - image = image.initByReferencingFile(path); - dockImage = image; - application.setApplicationIconImage(image); - } + } + + // Set the dock icon + int pid = OS.getpid (); + long /*int*/ ptr = OS.getenv (ascii ("APP_ICON_" + pid)); + if (ptr != 0) { + NSString path = NSString.stringWithUTF8String (ptr); + NSImage image = (NSImage) new NSImage().alloc(); + image = image.initByReferencingFile(path); + dockImage = image; + application.setApplicationIconImage(image); } String className = "SWTApplication"; @@ -930,6 +936,50 @@ systemUIOptions = bufferOptions[0]; } +/** + * Register a non-bundled application with Launch Services, using the JavaRuntimeSupport framework. + * This causes the app to show up in the dock, using the specified name. (The dock icon isn't set since, + * unlike the name, the icon may be changed anytime.) + * This framework is public and supposedly supported, but documentation is nearly non-existent. + *

+ * Method signature and keys are defined in + * /System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/Headers/JRSAppKitAWT.h + * Some corresponding properties are defined in + * JavaSystemProperties.html + * and are correlated with Launch Services keys in + * LaunchServicesKeys.html. + *

+ * Seems not to work on OS X 10.9(.0) yet. + * @return true iff the application was successfully registered + */ +private static boolean registerApplication() { + NSString appName = getApplicationName(); + if (OS.class_JRSAppKitAWT != 0) { + NSDictionary dict = NSMutableDictionary.dictionaryWithObject(appName, NSString.stringWith("JRSAppNameKey")); + + // TODO Skip this if bundled? Might affect icon and localized names. + // Without this, the dock name and icon will be taken from [NSBundle mainBundle]. + dict.setValue(NSNumber.numberWithBool(true), NSString.stringWith("JRSAppIsCommandLineKey")); + + if (Boolean.getBoolean("apple.awt.UIElement")) { + // Is an "agent app". Not shown in the dock, but can show UI. + // Corresponds to the LSUIElement key in Info.plist. + dict.setValue(NSNumber.numberWithBool(true), NSString.stringWith("JRSAppIsUIElementKey")); + } + + if (Boolean.getBoolean("apple.awt.BackgroundOnly")) { + // Is a "faceless background app". Does not show any UI. + // Corresponds to the LSBackgroundOnly key in Info.plist. + dict.setValue(NSNumber.numberWithBool(true), NSString.stringWith("JRSAppIsBackgroundOnlyKey")); + } + + // The "AWT" in these names are historical artifacts and has no significance. + OS.objc_msgSend(OS.class_JRSAppKitAWT, OS.sel_registerAWTAppWithOptions_, dict.id); + return true; + } + return false; +} + void createMainMenu () { NSString appName = getApplicationName(); NSString emptyStr = NSString.string();