Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2014-10-23 08:27:51 +0000
committerEike Stepper2014-10-23 08:27:51 +0000
commit882b969cbdf181d202381ce132a44c273d9cc403 (patch)
tree27902444dc4550bd3109a15b9bf8e46cf46ee720
parent1fe617969dd5d51b8c98a8b7330e8211b695801d (diff)
downloadorg.eclipse.oomph-882b969cbdf181d202381ce132a44c273d9cc403.tar.gz
org.eclipse.oomph-882b969cbdf181d202381ce132a44c273d9cc403.tar.xz
org.eclipse.oomph-882b969cbdf181d202381ce132a44c273d9cc403.zip
[440389] [MacOS] Clicking application menu "About setup-eclipse" has no effect
https://bugs.eclipse.org/bugs/show_bug.cgi?id=440389
-rw-r--r--plugins/org.eclipse.oomph.setup.installer/src/org/eclipse/oomph/setup/internal/installer/CocoaUtil.java183
-rw-r--r--plugins/org.eclipse.oomph.setup.installer/src/org/eclipse/oomph/setup/internal/installer/InstallerApplication.java28
2 files changed, 211 insertions, 0 deletions
diff --git a/plugins/org.eclipse.oomph.setup.installer/src/org/eclipse/oomph/setup/internal/installer/CocoaUtil.java b/plugins/org.eclipse.oomph.setup.installer/src/org/eclipse/oomph/setup/internal/installer/CocoaUtil.java
new file mode 100644
index 000000000..8635a7425
--- /dev/null
+++ b/plugins/org.eclipse.oomph.setup.installer/src/org/eclipse/oomph/setup/internal/installer/CocoaUtil.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2014 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.oomph.setup.internal.installer;
+
+import org.eclipse.oomph.util.ReflectUtil;
+
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.widgets.Display;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author Eike Stepper
+ */
+public final class CocoaUtil
+{
+ @SuppressWarnings("restriction")
+ private static final boolean LONG_POINTERS = org.eclipse.swt.internal.C.PTR_SIZEOF == 8;
+
+ private static final int ABOUT_ITEM_INDEX = 0;
+
+ private static final int PREFERENCES_ITEM_INDEX = 2;
+
+ private static final int QUIT_ITEM_INDEX = 10;
+
+ private static final String TYPES = "@:@";
+
+ private static Object invoke(Method method, Object target, Object... arguments)
+ {
+ return ReflectUtil.invokeMethod(method, target, arguments);
+ }
+
+ private static long pointer(Method method, Object target, Object... arguments)
+ {
+ Object pointer = invoke(method, target, arguments);
+ if (pointer instanceof Long)
+ {
+ return (Long)pointer;
+ }
+
+ if (pointer instanceof Integer)
+ {
+ return (Integer)pointer;
+ }
+
+ return 0;
+ }
+
+ private static Object adjust(long value)
+ {
+ if (LONG_POINTERS)
+ {
+ return value;
+ }
+
+ return (int)value;
+ }
+
+ public static void register(Display display, final Runnable about, final Runnable preferences, final Runnable quit)
+ {
+ try
+ {
+ final Class<?> Callback = Class.forName("org.eclipse.swt.internal.Callback");
+ final Method Callback_getAddress = ReflectUtil.getMethod(Callback, "getAddress");
+ final Method Callback_dispose = ReflectUtil.getMethod(Callback, "dispose");
+
+ final Class<?> OS = Class.forName("org.eclipse.swt.internal.cocoa.OS");
+ final Method OS_sel_registerName = ReflectUtil.getMethod(OS, "sel_registerName", String.class);
+ final Method OS_objc_lookUpClass = ReflectUtil.getMethod(OS, "objc_lookUpClass", String.class);
+ final Method OS_class_addMethod = ReflectUtil.getMethod(OS, "class_addMethod", long.class, long.class, long.class, String.class);
+
+ final Class<?> NSApplication = Class.forName("org.eclipse.swt.internal.cocoa.NSApplication");
+ final Method NSApplication_sharedApplication = ReflectUtil.getMethod(NSApplication, "sharedApplication");
+ final Method NSApplication_mainMenu = ReflectUtil.getMethod(NSApplication, "mainMenu");
+
+ final Class<?> NSMenu = Class.forName("org.eclipse.swt.internal.cocoa.NSMenu");
+ final Method NSMenu_itemAtIndex = ReflectUtil.getMethod(NSMenu, "itemAtIndex", long.class);
+ final Method NSMenu_submenu = ReflectUtil.getMethod(NSMenu, "submenu");
+
+ final Class<?> NSString = Class.forName("org.eclipse.swt.internal.cocoa.NSString");
+ final Method NSString_stringWith = ReflectUtil.getMethod(NSString, "stringWith", String.class);
+
+ final Class<?> NSMenuItem = Class.forName("org.eclipse.swt.internal.cocoa.NSMenuItem");
+ final Method NSMenuItem_setTitle = ReflectUtil.getMethod(NSMenuItem, "setTitle", String.class);
+ final Method NSMenuItem_setEnabled = ReflectUtil.getMethod(NSMenuItem, "setEnabled", boolean.class);
+ final Method NSMenuItem_setAction = ReflectUtil.getMethod(NSMenuItem, "setAction", long.class);
+
+ final long aboutItemSelected = pointer(OS_sel_registerName, null, "aboutMenuItemSelected:");
+ final long preferencesItemSelected = pointer(OS_sel_registerName, null, "preferencesMenuItemSelected:");
+ final long quitItemSelected = pointer(OS_sel_registerName, null, "quitMenuItemSelected:");
+
+ Object target = new Object()
+ {
+ @SuppressWarnings("unused")
+ int actionProc(int id, int sel, int arg2)
+ {
+ if (sel == aboutItemSelected)
+ {
+ if (about != null)
+ {
+ about.run();
+ }
+ }
+ else if (sel == preferencesItemSelected)
+ {
+ if (preferences != null)
+ {
+ preferences.run();
+ }
+ }
+ else if (sel == quitItemSelected)
+ {
+ if (quit != null)
+ {
+ quit.run();
+ }
+ }
+
+ return 0;
+ }
+ };
+
+ @SuppressWarnings("restriction")
+ final org.eclipse.swt.internal.Callback callback = new org.eclipse.swt.internal.Callback(target, "actionProc", 3);
+ final long callbackPointer = pointer(Callback_getAddress, callback);
+ if (callbackPointer == 0)
+ {
+ throw new SWTException("No more callbacks");
+ }
+
+ final long classPointer = pointer(OS_objc_lookUpClass, null, "SWTApplicationDelegate");
+ invoke(OS_class_addMethod, null, adjust(classPointer), adjust(aboutItemSelected), adjust(callbackPointer), TYPES);
+ invoke(OS_class_addMethod, null, adjust(classPointer), adjust(preferencesItemSelected), adjust(callbackPointer), TYPES);
+ invoke(OS_class_addMethod, null, adjust(classPointer), adjust(quitItemSelected), adjust(callbackPointer), TYPES);
+
+ final Object application = invoke(NSApplication_sharedApplication, null);
+ final Object mainMenu = invoke(NSApplication_mainMenu, application);
+ final Object mainItem = invoke(NSMenu_itemAtIndex, mainMenu, adjust(0));
+ final Object appMenu = invoke(NSMenu_submenu, mainItem);
+
+ final Object aboutItem = invoke(NSMenu_itemAtIndex, appMenu, adjust(ABOUT_ITEM_INDEX));
+ final Object preferencesItem = invoke(NSMenu_itemAtIndex, appMenu, adjust(PREFERENCES_ITEM_INDEX));
+ final Object quitItem = invoke(NSMenu_itemAtIndex, appMenu, adjust(QUIT_ITEM_INDEX));
+
+ final String appName = Display.getAppName();
+ if (appName != null)
+ {
+ final Object aboutLabel = invoke(NSString_stringWith, null, "About " + appName);
+ invoke(NSMenuItem_setTitle, aboutItem, aboutLabel);
+
+ final Object quitLabel = invoke(NSString_stringWith, null, "Quit " + appName);
+ invoke(NSMenuItem_setTitle, quitItem, quitLabel);
+ }
+
+ invoke(NSMenuItem_setAction, aboutItem, adjust(aboutItemSelected));
+ invoke(NSMenuItem_setAction, preferencesItem, adjust(preferencesItemSelected));
+ invoke(NSMenuItem_setAction, quitItem, adjust(quitItemSelected));
+
+ invoke(NSMenuItem_setEnabled, preferencesItem, true);
+ invoke(NSMenuItem_setEnabled, quitItem, true);
+
+ display.disposeExec(new Runnable()
+ {
+ public void run()
+ {
+ invoke(Callback_dispose, callback);
+ }
+ });
+ }
+ catch (Throwable t)
+ {
+ t.printStackTrace();
+ }
+ }
+}
diff --git a/plugins/org.eclipse.oomph.setup.installer/src/org/eclipse/oomph/setup/internal/installer/InstallerApplication.java b/plugins/org.eclipse.oomph.setup.installer/src/org/eclipse/oomph/setup/internal/installer/InstallerApplication.java
index 6bee46249..0135d03ce 100644
--- a/plugins/org.eclipse.oomph.setup.installer/src/org/eclipse/oomph/setup/internal/installer/InstallerApplication.java
+++ b/plugins/org.eclipse.oomph.setup.installer/src/org/eclipse/oomph/setup/internal/installer/InstallerApplication.java
@@ -65,6 +65,34 @@ public class InstallerApplication implements IApplication
try
{
final Display display = Display.getDefault();
+ Display.setAppName("Oomph-Installer");
+
+ // if (Platform.WS_COCOA.equals(Platform.getWS()))
+ // {
+ // Runnable about = new Runnable()
+ // {
+ // public void run()
+ // {
+ // }
+ // };
+ //
+ // Runnable preferences = new Runnable()
+ // {
+ // public void run()
+ // {
+ // }
+ // };
+ //
+ // Runnable quit = new Runnable()
+ // {
+ // public void run()
+ // {
+ // }
+ // };
+ //
+ // CocoaUtil.register(display, about, preferences, quit);
+ // }
+
display.asyncExec(new Runnable()
{
public void run()

Back to the top