With joy, this problem persists into 4.4.2.
At its base, the issue is the compatibility layer WorkbenchPart.getViewReferences() only searches the currently active perspective. This behavior is different than the 3.x. The relevant code from the 4.4.2 Eclipse WorkbenchPart is here (notice the call to getCurrentPerspective()).
public IViewReference[] getViewReferences() {
MPerspective perspective = getCurrentPerspective();
if (perspective != null) {
List<MPlaceholder> placeholders = modelService.findElements(window, null,
MPlaceholder.class, null, EModelService.PRESENTATION);
List<IViewReference> visibleReferences = new ArrayList<IViewReference>();
for (ViewReference reference : viewReferences) {
for (MPlaceholder placeholder : placeholders) {
if (reference.getModel() == placeholder.getRef()
&& placeholder.isToBeRendered()) {
// only rendered placeholders are valid view references
visibleReferences.add(reference);
}
}
}
return visibleReferences.toArray(new IViewReference[visibleReferences.size()]);
}
return new IViewReference[0];
}
Therefore, if one has a view open and then changes to a perspective where that view is not shown, the saveState() method will not be called.
We have added an OSGI event listener for the UIEvents.UILifeCycle.appShutdownStarted and made a call to the saveState(). However, it is necessary to obtain the IMemento manually, since it is not present. Example code is in the org.eclipse.ui.internal.ViewReference (http://grepcode.com/file/repository.grepcode.com/java/eclipse.org/4.2.2/org.eclipse.ui/workbench/3.104.0/org/eclipse/ui/internal/ViewReference.java#ViewReference).
One could also add a part close listener with the IPartListener class to potentially persist settings if the user closes the view rather than application shutting down.
We have not found an OSGI event for the part being closed, but there may be one.
This discussion (Eclipse call ViewPart saveState on View close) suggested using IDialogSettings rather the IMemento. This discussion also proposed perhaps adding something into the dispose() method, but it is unclear how many resources are necessarily still available at the point of the dispose() being called.