Fix(3) for Bug 424489 - [Perspectives] An alternative to Min / Max
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/TrimStack.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/TrimStack.java
index 7c7ecd8..547c57b 100644
--- a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/TrimStack.java
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/TrimStack.java
@@ -104,6 +104,7 @@
 	 */
 	private Menu trimStackMenu;
 
+	private boolean cachedUseOverlays = true;
 	private boolean isShowing = false;
 	private MUIElement minimizedElement;
 	private Composite clientAreaComposite;
@@ -257,13 +258,21 @@
 			showStack(false);
 		}
 	};
+	
+	// Close any open stacks before shutting down
+	private EventHandler shutdownHandler = new EventHandler() {
+		public void handleEvent(org.osgi.service.event.Event event) {
+			showStack(false);
+		}
+	};
 
 	private MAddon minMaxAddon;
 
 	@Inject
 	private void setMinMaxElement(MApplication theApp) {
 		for (MAddon addon : theApp.getAddons()) {
-			if (addon.getContributionURI().contains("MinMaxAddon")) { //$NON-NLS-1$
+			String uri = addon.getContributionURI();
+			if (uri != null && uri.contains("MinMaxAddon")) { //$NON-NLS-1$
 				minMaxAddon = addon;
 			}
 		}
@@ -489,6 +498,7 @@
 		eventBroker.subscribe(UIEvents.UIElement.TOPIC_WIDGET, widgetHandler);
 		eventBroker.subscribe(UIEvents.UILifeCycle.BRINGTOTOP, openHandler);
 		eventBroker.subscribe(UIEvents.UILifeCycle.ACTIVATE, closeHandler);
+		eventBroker.subscribe(UIEvents.UILifeCycle.APP_SHUTDOWN_STARTED, shutdownHandler);
 	}
 
 	/**
@@ -521,11 +531,10 @@
 		trimStackTB = new ToolBar(parent, orientation | SWT.FLAT | SWT.WRAP);
 		trimStackTB.addDisposeListener(new DisposeListener() {
 			public void widgetDisposed(DisposeEvent e) {
+				showStack(false);
+
 				trimStackTB = null;
 				trimStackMenu = null;
-
-				if (isShowing && hostPane != null && !hostPane.isDisposed())
-					showStack(false);
 			}
 		});
 
@@ -888,14 +897,14 @@
 
 				// Cache the value to ensure that a stack is hidden using the same mode it was
 				// opened in
-				trimStackTB.setData(USE_OVERLAYS_KEY, true);
+				cachedUseOverlays = true;
 			} else {
 				minimizedElement.setVisible(true);
 				ctrl.addListener(SWT.Traverse, escapeListener);
 
 				// Cache the value to ensure that a stack is hidden using the same mode it was
 				// opened in
-				trimStackTB.setData(USE_OVERLAYS_KEY, false);
+				cachedUseOverlays = false;
 			}
 
 			isShowing = true;
@@ -952,8 +961,7 @@
 
 			fixToolItemSelection();
 		} else if (!show && isShowing) {
-			boolean cachedOverlayState = (Boolean) trimStackTB.getData(USE_OVERLAYS_KEY);
-			if (cachedOverlayState) {
+			if (cachedUseOverlays) {
 				// Check to ensure that the client area is non-null since the
 				// trimstack may be currently hosted in the limbo shell
 				if (clientAreaComposite != null) {
@@ -966,7 +974,8 @@
 					hostPane.setVisible(false);
 				}
 			} else {
-				ctrl.removeListener(SWT.Traverse, escapeListener);
+				if (ctrl != null && !ctrl.isDisposed())
+					ctrl.removeListener(SWT.Traverse, escapeListener);
 				minimizedElement.setVisible(false);
 			}
 
diff --git a/bundles/org.eclipse.e4.ui.workbench/.settings/.api_filters b/bundles/org.eclipse.e4.ui.workbench/.settings/.api_filters
index 008fb23..c557e1d 100644
--- a/bundles/org.eclipse.e4.ui.workbench/.settings/.api_filters
+++ b/bundles/org.eclipse.e4.ui.workbench/.settings/.api_filters
@@ -22,6 +22,12 @@
         </filter>
     </resource>
     <resource path="src/org/eclipse/e4/ui/workbench/UIEvents.java" type="org.eclipse.e4.ui.workbench.UIEvents$UILifeCycle">
+        <filter id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.UILifeCycle"/>
+                <message_argument value="APP_SHUTDOWN_STARTED"/>
+            </message_arguments>
+        </filter>
         <filter comment="All of the subinterfaces shouldn't be subclassed either" id="403767336">
             <message_arguments>
                 <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.UILifeCycle"/>
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/UIEvents.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/UIEvents.java
index 499e03d..3854eb4 100644
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/UIEvents.java
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/UIEvents.java
@@ -16,6 +16,7 @@
 import java.util.Map;
 import org.eclipse.e4.core.contexts.IEclipseContext;
 import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.model.application.MApplication;
 import org.eclipse.e4.ui.model.application.ui.MUIElement;
 import org.eclipse.e4.ui.model.internal.ModelUtils;
 import org.osgi.service.event.Event;
@@ -259,6 +260,12 @@
 		 * Sent when application startup is complete
 		 */
 		public static final String APP_STARTUP_COMPLETE = TOPIC + TOPIC_SEP + "appStartupComplete"; //$NON-NLS-1$
+		/**
+		 * Sent when application shutdown is starting
+		 * 
+		 * @since 1.1
+		 */
+		public static final String APP_SHUTDOWN_STARTED = TOPIC + TOPIC_SEP + "appShutdownStarted"; //$NON-NLS-1$
 
 		/**
 		 * Sent when the theme is changed
@@ -314,7 +321,8 @@
 		if (uiElement == null || !(uiElement instanceof MUIElement))
 			return false;
 
-		IEclipseContext context = ModelUtils.getContainingContext((MUIElement) uiElement);
+		IEclipseContext context = uiElement instanceof MApplication ? ((MApplication) uiElement)
+				.getContext() : ModelUtils.getContainingContext((MUIElement) uiElement);
 		if (context == null)
 			return false;
 
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/Workbench.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/Workbench.java
index 679e969..8f1b5ec 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/Workbench.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/Workbench.java
@@ -1042,6 +1042,8 @@
 	 * @return true if the close succeeded, and false otherwise
 	 */
 	private boolean busyClose(final boolean force) {
+		// Fire an E4 lifecycle notification
+		UIEvents.publishEvent(UIEvents.UILifeCycle.APP_SHUTDOWN_STARTED, application);
 
 		// notify the advisor of preShutdown and allow it to veto if not forced
 		isClosing = advisor.preShutdown();