Reputation:
I'd like to use a Java application to display text in the system tray / task bar on OS X in a native way. I'd like to do this by invoking setTitle
on the NSStatusItem
(like in this example). I've never accessed the underlying native libraries in SWT, and I'm having trouble with it.
Someone on this thread demonstrated how to invoke an Objective-C method to change a property of a window in SWT (the full-screen button). Here is his/her code:
Field field = Control.class.getDeclaredField("view");
Object /*NSView*/ view = field.get(rShell);
if (view != null)
{
Class<?> c = Class.forName("org.eclipse.swt.internal.cocoa.NSView");
Object /*NSWindow*/ window = c.getDeclaredMethod("window").invoke(view);
c = Class.forName("org.eclipse.swt.internal.cocoa.NSWindow");
Method setCollectionBehavior = c.getDeclaredMethod(
"setCollectionBehavior", JVM.is64bit() ? long.class : int.class);
setCollectionBehavior.invoke(window, getFullScreenMask());
}
So I suppose this would result in this Objective-C code:
[window setCollectionBehaviour:1<<7];
Now I'd like to do the same for an SWT TrayItem
. The goal is to get the equivalent of this Objective-C code:
[statusItem setTitle:@"Status"];
But I'm getting the following exception:
Exception in thread "main" java.lang.IllegalArgumentException: Can not set org.eclipse.swt.internal.cocoa.NSView field org.eclipse.swt.widgets.Control.view to org.eclipse.swt.widgets.TrayItem
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:37)
at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:18)
at java.lang.reflect.Field.get(Field.java:358)
at com.teez.status.MainStatus.main(MainStatus.java:35)
I'm not sure what this means. I marked the line where the exception is thrown. What other issues could I run into while attempting this? Here is my code:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tray;
import org.eclipse.swt.widgets.TrayItem;
public class MainStatus {
public static void main(String[] args) throws Exception {
Display display = new Display();
Shell shell = new Shell(display);
Tray tray = display.getSystemTray();
if (tray != null) {
TrayItem item = new TrayItem(tray, SWT.NONE);
Field field = Control.class.getDeclaredField("view");
Object /*NSView*/ view = field.get(item); //Exception thrown here
if (view != null)
{
Class<?> c = Class.forName("org.eclipse.swt.internal.cocoa.NSView");
Object /*NSWindow*/ window = c.getDeclaredMethod("window").invoke(view);
c = Class.forName("org.eclipse.swt.internal.cocoa.NSStatusItem");
Method setCollectionBehavior = c.getDeclaredMethod("setTitle", long.class);
setCollectionBehavior.invoke(window, "Desired title");
}
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();
}
display.dispose ();
}
}
}
Edit: Thanks Eugene for solving this problem, but the text is still not showing up on the status bar, so I asked another question here.
Upvotes: 2
Views: 248