Another question from the inbox:
I have an SWT app on OS X that wants to have the “toggle toolbar” button in the upper right corner of the window trim. I see that Eclipse has this button but I don’t see API in SWT to make it happen. How can I have this button in my app?”
Unfortunately, there is no API for this feature. Back in 3.2 we added this feature by adding code to the org.eclipse.ui.carbon fragment that called SWT internals. The code to do this for your own SWT app would look something like this:
import org.eclipse.swt.SWT;
import org.eclipse.swt.internal.Callback;
import org.eclipse.swt.internal.carbon.OS;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Widget;
public class ToolbarShellHandler {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell();
shell.setLayout(new GridLayout());
Button button = new Button(shell, SWT.PUSH);
button.setText(”Toolbar”);
Text text = new Text(shell, SWT.READ_ONLY);
text.setText(”Shell contents”);
ToolbarShellHandler target = new ToolbarShellHandler();
target.hookHandler(shell);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
private void hookHandler(Shell shell) {
// create a callback that will be invoked when the button is pressed.
final Callback commandCallback = new Callback(this, “toolbarProc”, 3); //$NON-NLS-1$
int commandProc = commandCallback.getAddress();
if (commandProc == 0) {
commandCallback.dispose();
return; // give up
}
shell.getDisplay().disposeExec(new Runnable() {
public void run() {
commandCallback.dispose();
}
});
// add the button to the window trim
int windowHandle = OS.GetControlOwner(shell.handle);
OS.ChangeWindowAttributes(windowHandle, OS.kWindowToolbarButtonAttribute, 0);
int[] mask = new int[] {
OS.kEventClassWindow, OS.kEventWindowToolbarSwitchMode
};
// register the handler with the OS
OS.InstallEventHandler(OS.GetApplicationEventTarget(), commandProc, mask.length / 2, mask, 0, null);
}
public int toolbarProc(int nextHandler, int theEvent, int userData) {
int eventKind = OS.GetEventKind(theEvent);
if (eventKind != OS.kEventWindowToolbarSwitchMode) // only handle the
// toolbar events
return OS.eventNotHandledErr;
int[] theWindow = new int[1];
// get the even window
OS.GetEventParameter(theEvent, OS.kEventParamDirectObject, OS.typeWindowRef, null, 4, null, theWindow);
int[] theRoot = new int[1];
// find the root control for the window
OS.GetRootControl(theWindow[0], theRoot);
Widget widget = Display.getCurrent().findWidget(theRoot[0]);
if (!(widget instanceof Shell)) { // only proceed if its a shell we’ve
// found
return OS.eventNotHandledErr;
}
Shell shellAffected = (Shell) widget; // do cool stuff with the shell
boolean visible = !shellAffected.getChildren()[0].getVisible();
shellAffected.getChildren()[0].setVisible(visible);
return OS.noErr;
}
}
There are two basic steps to the process. First you tweak the application shell to have the correct style bits. This causes the button to appear. This is accomplished by the OS call
. Next, you register with the OS a handler that will be called in the event that the
kEventWindowToolbarSwitchMode
Apple events are fired. We do this by creating a Callback class that points at a target object (in this case, the
instance) and is given a method name (”toolbarProc”). When this even is received the Callback object reflectively calls the provided method. In this method is where you do your interesting work. In our example above this method looks for the window control responsible for generating the event, finds its corresponding SWT Shell object, and hides/un-hides the first control as appropriate.
You can use such hacks for more than just the toolbar toggle button, however. Look at the CarbonUIEnhancer class for code that hooks not only the toogle button but also the application preference and about commands.






