Bug 559579 - Wrong Debug view selection, if view is opened post launch

When opening the Debug view after a Java launch is started, the already
suspended threads are not recorded in ThreadEventHandler.fThreadQueue.

As a result, the following sequence breaks the Debug view selection:

1. Open the Debug view after Thread-1 is already suspended.
2. Thread-2 becomes suspended.
3. Resume Thread-2.
4. Thread-1 (which is still suspended) is not selected. Instead, e.g.
the debug launch itself is selected, or the resumed Thread-2 is
selected.

This behavior is not seen if the Debug view is opened prior the Java
application debug launch.

In the case of JDT, the set of suspended threads
ThreadEventHandler.fThreadQueue is updated on JVM thread suspend events
and Debug view tree expand events. However, the way
TreeModelContentProvider "expands" suspended threads does not trigger
SWT expand events, when the Debug view is opened and
JavaDebugTargetProxy installs itself.

This change ensures that JavaThreadEventHandler is initialized with the
already suspended threads, on Debug view open. JavaDebugTargetProxy will
go over the suspended thread delta and add suspended threads to
JavaThreadEventHandler.fThreadQueue.

Change-Id: I9dfc581b25105bbca0a82f9bf974a7bc7c496e4f
Signed-off-by: Simeon Andreev <simeon.danailov.andreev@gmail.com>
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/threadgroups/JavaDebugTargetProxy.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/threadgroups/JavaDebugTargetProxy.java
index 5fd7379..3102884 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/threadgroups/JavaDebugTargetProxy.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/threadgroups/JavaDebugTargetProxy.java
@@ -26,12 +26,14 @@
 import org.eclipse.debug.core.model.IStackFrame;
 import org.eclipse.debug.core.model.IThread;
 import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDeltaVisitor;
 import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
 import org.eclipse.debug.internal.ui.viewers.update.DebugEventHandler;
 import org.eclipse.debug.internal.ui.viewers.update.DebugTargetEventHandler;
 import org.eclipse.debug.internal.ui.viewers.update.DebugTargetProxy;
 import org.eclipse.debug.internal.ui.viewers.update.StackFrameEventHandler;
 import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.debug.core.IJavaThread;
 import org.eclipse.jdt.debug.ui.JavaDebugUtils;
 import org.eclipse.jdt.internal.debug.ui.monitors.JavaElementContentProvider;
 import org.eclipse.jdt.internal.debug.ui.snippeteditor.ScrapbookLauncher;
@@ -125,6 +127,8 @@
                     return;
                 }
             }
+			// Bug 559579: ensure the JavaThreadEventHandler has all suspended threads in case the Debug view is opened post launch
+			addSuspendedThreadsToThreadHandler(delta);
             // expand the target if no suspended thread
             fireModelChanged(delta);
         }
@@ -159,4 +163,21 @@
 		}
 		return stackFrameIndex;
 	}
+
+	private void addSuspendedThreadsToThreadHandler(ModelDelta delta) {
+		delta.accept(new IModelDeltaVisitor() {
+			@Override
+			public boolean visit(IModelDelta delta, int depth) {
+				Object element = delta.getElement();
+				if (element instanceof IJavaThread) {
+					IJavaThread thread = (IJavaThread) element;
+					boolean suspended = thread.isSuspended();
+					if (suspended) {
+						fThreadEventHandler.addSuspendedThread(thread);
+					}
+				}
+				return true;
+			}
+		});
+	}
 }
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/threadgroups/JavaThreadEventHandler.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/threadgroups/JavaThreadEventHandler.java
index d54dbac..aea73c1 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/threadgroups/JavaThreadEventHandler.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/threadgroups/JavaThreadEventHandler.java
@@ -305,6 +305,10 @@
 		}
 	}
 
+	void addSuspendedThread(IJavaThread thread) {
+		queueSuspendedThread(thread);
+	}
+
 	/**
 	 * Do not update for quiet resume/suspend
 	 */