Bug 117095 - [flex-hierarchy] resuming one thread does not select next suspended thread
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewer.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewer.java index 77f6f37..90ec23e 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewer.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewer.java
@@ -936,6 +936,16 @@ } } + synchronized void remove(final Widget widget) { + preservingSelection(new Runnable() { + public void run() { + Object element = widget.getData(); + unmap(element, widget); + widget.dispose(); + } + }); + } + void setLabels(Widget widget, String[] text, ImageDescriptor[] image) { if (widget instanceof TreeItem) { TreeItem item = (TreeItem) widget;
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/RemoveRequestMonitor.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/RemoveRequestMonitor.java index 989b618..33b0049 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/RemoveRequestMonitor.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/RemoveRequestMonitor.java
@@ -33,10 +33,7 @@ * @see org.eclipse.debug.internal.ui.viewers.AsynchronousRequestMonitor#performUpdate() */ protected void performUpdate() { - Widget widget = getWidget(); - Object element = widget.getData(); - getViewer().unmap(element, widget); - widget.dispose(); + ((AsynchronousTreeViewer)getViewer()).remove(getWidget()); } }
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/DefaultSelectionPolicy.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/DefaultSelectionPolicy.java index 68db304..516e298 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/DefaultSelectionPolicy.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/DefaultSelectionPolicy.java
@@ -83,7 +83,7 @@ if (existing instanceof IStackFrame && candidate instanceof IStackFrame) { IStackFrame curr = (IStackFrame) existing; IStackFrame next = (IStackFrame) candidate; - return curr.getThread().equals(next.getThread()); + return curr.getThread().equals(next.getThread()) || !isSticky(existing); } return !isSticky(existing); }
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/ThreadEventHandler.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/ThreadEventHandler.java index e6e4405..ef54077 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/ThreadEventHandler.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/ThreadEventHandler.java
@@ -11,7 +11,9 @@ package org.eclipse.debug.internal.ui.viewers.update; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.Map; +import java.util.Set; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugException; @@ -27,6 +29,13 @@ */ public class ThreadEventHandler extends DebugEventHandler { + /** + * Queue of suspended threads to choose from when needing + * to select a thread when another is resumed. Threads + * are added in the order they suspend. + */ + private Set fThreadQueue = new LinkedHashSet(); + /** * Map of previous TOS per thread */ @@ -44,6 +53,9 @@ synchronized (fLastTopFrame) { fLastTopFrame.clear(); } + synchronized (fThreadQueue) { + fThreadQueue.clear(); + } super.dispose(); } @@ -59,6 +71,7 @@ } catch (DebugException e) { } } else { + queueSuspendedThread(event); fireDeltaUpdatingTopFrame(thread, IModelDelta.NOCHANGE); } } @@ -74,7 +87,12 @@ } protected void handleResume(DebugEvent event) { - fireDeltaAndClearTopFrame((IThread) event.getSource(), IModelDelta.CHANGED | IModelDelta.STATE | IModelDelta.CONTENT); + IThread thread = removeSuspendedThread(event); + fireDeltaAndClearTopFrame(thread, IModelDelta.CHANGED | IModelDelta.STATE | IModelDelta.CONTENT); + thread = getNextSuspendedThread(); + if (thread != null) { + fireDeltaUpdatingTopFrame(thread, IModelDelta.NOCHANGE); + } } protected void handleCreate(DebugEvent event) { @@ -90,11 +108,13 @@ } protected void handleLateSuspend(DebugEvent suspend, DebugEvent resume) { - fireDeltaUpdatingTopFrame((IThread) suspend.getSource(), IModelDelta.CHANGED | IModelDelta.CONTENT | IModelDelta.EXPAND); + IThread thread = queueSuspendedThread(suspend); + fireDeltaUpdatingTopFrame(thread, IModelDelta.CHANGED | IModelDelta.CONTENT | IModelDelta.EXPAND); } protected void handleSuspendTimeout(DebugEvent event) { - fireDeltaAndClearTopFrame((IThread) event.getSource(), IModelDelta.CHANGED | IModelDelta.CONTENT); + IThread thread = removeSuspendedThread(event); + fireDeltaAndClearTopFrame(thread, IModelDelta.CHANGED | IModelDelta.CONTENT); } private IModelDeltaNode buildBaseDelta(ModelDelta delta, IThread thread) { @@ -143,5 +163,30 @@ protected boolean handlesEvent(DebugEvent event) { return event.getSource() instanceof IThread; } + + protected IThread queueSuspendedThread(DebugEvent event) { + IThread thread = (IThread) event.getSource(); + synchronized (fThreadQueue) { + fThreadQueue.add(thread); + } + return thread; + } + + protected IThread removeSuspendedThread(DebugEvent event) { + IThread thread = (IThread)event.getSource(); + synchronized (fThreadQueue) { + fThreadQueue.remove(thread); + } + return thread; + } + + protected IThread getNextSuspendedThread() { + synchronized (fThreadQueue) { + if (!fThreadQueue.isEmpty()) { + return (IThread) fThreadQueue.iterator().next(); + } + } + return null; + } }