Fixed bug 391626: [Compatibility] e4 does not implement the
post-selection concept
diff --git a/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF
index 39a8049..1bf44b9 100644
--- a/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-SymbolicName: org.eclipse.e4.ui.workbench;singleton:=true
-Bundle-Version: 0.10.100.qualifier
+Bundle-Version: 0.11.0.qualifier
 Bundle-Name: %pluginName
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/SelectionAggregator.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/SelectionAggregator.java
index 16cc2f7..18a21ad 100644
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/SelectionAggregator.java
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/SelectionAggregator.java
@@ -39,9 +39,12 @@
 public class SelectionAggregator {
 
 	static final String OUT_SELECTION = "org.eclipse.ui.output.selection"; //$NON-NLS-1$
+	static final String OUT_POST_SELECTION = "org.eclipse.ui.output.postSelection"; //$NON-NLS-1$
 
 	private ListenerList genericListeners = new ListenerList();
+	private ListenerList genericPostListeners = new ListenerList();
 	private Map<String, ListenerList> targetedListeners = new HashMap<String, ListenerList>();
+	private Map<String, ListenerList> targetedPostListeners = new HashMap<String, ListenerList>();
 	private Set<IEclipseContext> tracked = new HashSet<IEclipseContext>();
 
 	private EventHandler eventHandler = new EventHandler() {
@@ -80,7 +83,9 @@
 	@PreDestroy
 	void preDestroy() {
 		genericListeners.clear();
+		genericPostListeners.clear();
 		targetedListeners.clear();
+		targetedPostListeners.clear();
 
 		eventBroker.unsubscribe(eventHandler);
 	}
@@ -96,7 +101,11 @@
 			activePart = part;
 			IEclipseContext partContext = part.getContext();
 			// only notify listeners if the part actually posts selections
-			if (partContext.containsKey(OUT_SELECTION)) {
+			if (partContext.containsKey(OUT_POST_SELECTION)) {
+				Object selection = partContext.get(OUT_POST_SELECTION);
+				context.set(IServiceConstants.ACTIVE_SELECTION, selection);
+				notifyPostListeners(part, selection);
+			} else if (partContext.containsKey(OUT_SELECTION)) {
 				Object selection = partContext.get(OUT_SELECTION);
 				context.set(IServiceConstants.ACTIVE_SELECTION, selection);
 				notifyListeners(part, selection);
@@ -142,6 +151,43 @@
 		}
 	}
 
+	private void notifyPostListeners(final MPart part, final Object selection) {
+		for (Object listener : genericPostListeners.getListeners()) {
+			final ISelectionListener myListener = (ISelectionListener) listener;
+			SafeRunner.run(new ISafeRunnable() {
+				public void run() throws Exception {
+					myListener.selectionChanged(part, selection);
+				}
+
+				public void handleException(Throwable exception) {
+					logger.error(exception);
+				}
+			});
+		}
+		notifyTargetedPostListeners(part, selection);
+	}
+
+	private void notifyTargetedPostListeners(final MPart part, final Object selection) {
+		String id = part.getElementId();
+		if (id != null) {
+			ListenerList listenerList = targetedPostListeners.get(id);
+			if (listenerList != null) {
+				for (Object listener : listenerList.getListeners()) {
+					final ISelectionListener myListener = (ISelectionListener) listener;
+					SafeRunner.run(new ISafeRunnable() {
+						public void run() throws Exception {
+							myListener.selectionChanged(part, selection);
+						}
+
+						public void handleException(Throwable exception) {
+							logger.error(exception);
+						}
+					});
+				}
+			}
+		}
+	}
+
 	private void track(final MPart part) {
 		final IEclipseContext myContext = this.context;
 		IEclipseContext context = part.getContext();
@@ -159,6 +205,8 @@
 
 				public boolean changed(IEclipseContext context) {
 					final Object selection = context.get(OUT_SELECTION);
+					final Object postSelection = context.get(OUT_POST_SELECTION);
+					context.set(OUT_POST_SELECTION, null); // make sure it's gone until set again
 					if (initial) {
 						initial = false;
 						if (selection == null) {
@@ -170,19 +218,26 @@
 						myContext.set(IServiceConstants.ACTIVE_SELECTION, selection);
 						runExternalCode(new Runnable() {
 							public void run() {
-								notifyListeners(part, selection);
+								if (postSelection != null)
+									notifyPostListeners(part, selection);
+								else
+									notifyListeners(part, selection);
 							}
 						});
 					} else {
 						runExternalCode(new Runnable() {
 							public void run() {
-								notifyTargetedListeners(part, selection);
+								if (postSelection != null)
+									notifyTargetedPostListeners(part, selection);
+								else
+									notifyTargetedListeners(part, selection);
 							}
 						});
 						// we don't need to keep tracking non-active parts unless
 						// they have targeted listeners
 						String partId = part.getElementId();
-						boolean continueTracking = targetedListeners.containsKey(partId);
+						boolean continueTracking = targetedListeners.containsKey(partId)
+								|| targetedPostListeners.containsKey(partId);
 						if (!continueTracking) {
 							tracked.remove(part.getContext());
 						}
@@ -202,6 +257,10 @@
 		genericListeners.add(listener);
 	}
 
+	public void addPostSelectionListener(ISelectionListener listener) {
+		genericPostListeners.add(listener);
+	}
+
 	public void removeSelectionListener(ISelectionListener listener) {
 		// we may have been destroyed already, see bug 310113
 		if (context != null) {
@@ -209,6 +268,13 @@
 		}
 	}
 
+	public void removePostSelectionListener(ISelectionListener listener) {
+		// we may have been destroyed already, see bug 310113
+		if (context != null) {
+			genericPostListeners.remove(listener);
+		}
+	}
+
 	public void addSelectionListener(String partId, ISelectionListener listener) {
 		ListenerList listeners = targetedListeners.get(partId);
 		if (listeners == null) {
@@ -222,6 +288,19 @@
 			track(part);
 	}
 
+	public void addPostSelectionListener(String partId, ISelectionListener listener) {
+		ListenerList listeners = targetedPostListeners.get(partId);
+		if (listeners == null) {
+			listeners = new ListenerList();
+			targetedPostListeners.put(partId, listeners);
+		}
+		listeners.add(listener);
+
+		MPart part = partService.findPart(partId);
+		if (part != null)
+			track(part);
+	}
+
 	public void removeSelectionListener(String partId, ISelectionListener listener) {
 		// we may have been destroyed already, see bug 310113
 		if (context != null) {
@@ -232,6 +311,16 @@
 		}
 	}
 
+	public void removePostSelectionListener(String partId, ISelectionListener listener) {
+		// we may have been destroyed already, see bug 310113
+		if (context != null) {
+			ListenerList listeners = targetedPostListeners.get(partId);
+			if (listeners != null) {
+				listeners.remove(listener);
+			}
+		}
+	}
+
 	public Object getSelection(String partId) {
 		MPart part = partService.findPart(partId);
 		if (part == null) {
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/SelectionServiceImpl.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/SelectionServiceImpl.java
index 93c99b0..8655d75 100644
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/SelectionServiceImpl.java
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/SelectionServiceImpl.java
@@ -30,6 +30,10 @@
 		context.set(SelectionAggregator.OUT_SELECTION, selection);
 	}
 
+	public void setPostSelection(Object selection) {
+		context.set(SelectionAggregator.OUT_POST_SELECTION, selection);
+	}
+
 	public Object getSelection() {
 		return getServiceAggregator().getSelection();
 	}
@@ -54,6 +58,22 @@
 		getServiceAggregator().removeSelectionListener(partId, listener);
 	}
 
+	public void addPostSelectionListener(ISelectionListener listener) {
+		getServiceAggregator().addPostSelectionListener(listener);
+	}
+
+	public void removePostSelectionListener(ISelectionListener listener) {
+		getServiceAggregator().removePostSelectionListener(listener);
+	}
+
+	public void addPostSelectionListener(String partId, ISelectionListener listener) {
+		getServiceAggregator().addPostSelectionListener(partId, listener);
+	}
+
+	public void removePostSelectionListener(String partId, ISelectionListener listener) {
+		getServiceAggregator().removePostSelectionListener(partId, listener);
+	}
+
 	private SelectionAggregator getServiceAggregator() {
 		SelectionAggregator aggregator = context.get(SelectionAggregator.class);
 		if (aggregator != null)
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ESelectionService.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ESelectionService.java
index c2040e0..bd7d22c 100644
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ESelectionService.java
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ESelectionService.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2010 IBM Corporation and others.
+ * Copyright (c) 2009, 2012 IBM Corporation 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
@@ -28,6 +28,8 @@
 
 	public void setSelection(Object selection);
 
+	public void setPostSelection(Object selection);
+
 	public Object getSelection();
 
 	public Object getSelection(String partId);
@@ -39,4 +41,12 @@
 	public void addSelectionListener(String partId, ISelectionListener listener);
 
 	public void removeSelectionListener(String partId, ISelectionListener listener);
+
+	public void addPostSelectionListener(ISelectionListener listener);
+
+	public void removePostSelectionListener(ISelectionListener listener);
+
+	public void addPostSelectionListener(String partId, ISelectionListener listener);
+
+	public void removePostSelectionListener(String partId, ISelectionListener listener);
 }
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/CompatibilityPart.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/CompatibilityPart.java
index 6dac921..7089dd2 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/CompatibilityPart.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/CompatibilityPart.java
@@ -165,7 +165,14 @@
 
 				if (selectionProvider instanceof IPostSelectionProvider) {
 					((IPostSelectionProvider) selectionProvider)
-							.addPostSelectionChangedListener(this);
+							.addPostSelectionChangedListener(new ISelectionChangedListener() {
+
+								public void selectionChanged(SelectionChangedEvent e) {
+									ESelectionService selectionService = (ESelectionService) part
+											.getContext().get(ESelectionService.class.getName());
+									selectionService.setPostSelection(e.getSelection());
+								}
+							});
 				}
 			}
 		}
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/SelectionService.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/SelectionService.java
index bf376ae..a46c7a9 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/SelectionService.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/SelectionService.java
@@ -54,7 +54,9 @@
 	private IWorkbenchPart activePart;
 
 	private ListenerList listeners = new ListenerList();
+	private ListenerList postSelectionListeners = new ListenerList();
 	private Map<String, Set<ISelectionListener>> targetedListeners = new HashMap<String, Set<ISelectionListener>>();
+	private Map<String, Set<ISelectionListener>> targetedPostSelectionListeners = new HashMap<String, Set<ISelectionListener>>();
 
 	private org.eclipse.e4.ui.workbench.modeling.ISelectionListener listener = new org.eclipse.e4.ui.workbench.modeling.ISelectionListener() {
 		public void selectionChanged(MPart part, Object selection) {
@@ -74,6 +76,25 @@
 		}
 	};
 
+	private org.eclipse.e4.ui.workbench.modeling.ISelectionListener postListener = new org.eclipse.e4.ui.workbench.modeling.ISelectionListener() {
+		public void selectionChanged(MPart part, Object selection) {
+			selection = createCompatibilitySelection(selection);
+			context.set(ISources.ACTIVE_CURRENT_SELECTION_NAME, selection);
+
+			IEclipseContext applicationContext = application.getContext();
+			if (applicationContext.getActiveChild() == context) {
+				application.getContext().set(ISources.ACTIVE_CURRENT_SELECTION_NAME, selection);
+			}
+
+			Object client = part.getObject();
+			if (client instanceof CompatibilityPart) {
+				IWorkbenchPart workbenchPart = ((CompatibilityPart) client).getPart();
+				notifyPostSelectionListeners(part.getElementId(), workbenchPart,
+						(ISelection) selection);
+			}
+		}
+	};
+
 	private static ISelection createCompatibilitySelection(Object selection) {
 		if (selection instanceof ISelection) {
 			return (ISelection) selection;
@@ -122,10 +143,12 @@
 	void setSelectionService(@Optional ESelectionService selectionService) {
 		if (this.selectionService != null) {
 			this.selectionService.removeSelectionListener(listener);
+			this.selectionService.removePostSelectionListener(postListener);
 		}
 
 		if (selectionService != null) {
 			selectionService.addSelectionListener(listener);
+			selectionService.addPostSelectionListener(postListener);
 			this.selectionService = selectionService;
 		}
 	 }
@@ -149,6 +172,25 @@
 		}
 	}
 
+	private void notifyPostSelectionListeners(String id, IWorkbenchPart workbenchPart, ISelection selection) {
+		for (Object listener : postSelectionListeners.getListeners()) {
+			if (selection != null || listener instanceof INullSelectionListener) {
+				((ISelectionListener) listener).selectionChanged(workbenchPart, selection);
+			}
+		}
+		
+		if (id != null) {
+			Set<ISelectionListener> listeners = targetedPostSelectionListeners.get(id);
+			if (listeners != null) {
+				for (ISelectionListener listener : listeners) {
+					if (selection != null || listener instanceof INullSelectionListener) {
+						listener.selectionChanged(workbenchPart, selection);
+					}
+				}
+			}
+		}
+	}
+
 	/*
 	 * (non-Javadoc)
 	 * 
@@ -184,8 +226,7 @@
 	 * .ui.ISelectionListener)
 	 */
 	public void addPostSelectionListener(ISelectionListener listener) {
-		// TODO compat addPostSelectionListener
-		addSelectionListener(listener);
+		postSelectionListeners.add(listener);
 	}
 
 	/*
@@ -196,8 +237,12 @@
 	 * , org.eclipse.ui.ISelectionListener)
 	 */
 	public void addPostSelectionListener(String partId, ISelectionListener listener) {
-		// TODO compat addPostSelectionListener
-		addSelectionListener(partId, listener);
+		Set<ISelectionListener> listeners = targetedPostSelectionListeners.get(partId);
+		if (listeners == null) {
+			listeners = new HashSet<ISelectionListener>();
+			targetedPostSelectionListeners.put(partId, listeners);
+		}
+		listeners.add(listener);
 	}
 
 	/*
@@ -265,8 +310,7 @@
 	 * .ui.ISelectionListener)
 	 */
 	public void removePostSelectionListener(ISelectionListener listener) {
-		// TODO compat removePostSelectionListener
-		removeSelectionListener(listener);
+		postSelectionListeners.remove(listener);
 	}
 
 	/*
@@ -277,8 +321,10 @@
 	 * .String, org.eclipse.ui.ISelectionListener)
 	 */
 	public void removePostSelectionListener(String partId, ISelectionListener listener) {
-		// TODO compat removePostSelectionListener
-		removeSelectionListener(partId, listener);
+		Set<ISelectionListener> listeners = targetedPostSelectionListeners.get(partId);
+		if (listeners != null) {
+			listeners.remove(listener);
+		}
 	}
 
 	/*