Debugger: Add team event handling to expression window.
ExpressionEvaluationWindow: - Add team listener hooks for the various thread state changes. - Implement these to react accordingly and keep the thread/frame menus up to date with running program changes, whether due to user interaction in the main team window, or background activities of the debugged app. Previously the evaluation window needed to be closed and reopened to refresh these appropriately.
This commit is contained in:
+198
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015, Rene Gollent, [email protected].
|
||||
* Copyright 2014-2016, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#include "ExpressionEvaluationWindow.h"
|
||||
@@ -10,7 +10,9 @@
|
||||
#include <String.h>
|
||||
#include <TextControl.h>
|
||||
|
||||
#include "AutoLocker.h"
|
||||
#include <AutoDeleter.h>
|
||||
#include <AutoLocker.h>
|
||||
|
||||
#include "CppLanguage.h"
|
||||
#include "FunctionDebugInfo.h"
|
||||
#include "FunctionInstance.h"
|
||||
@@ -26,6 +28,9 @@
|
||||
|
||||
|
||||
enum {
|
||||
MSG_THREAD_ADDED = 'thad',
|
||||
MSG_THREAD_REMOVED = 'thar',
|
||||
|
||||
MSG_THREAD_SELECTION_CHANGED = 'thsc',
|
||||
MSG_FRAME_SELECTION_CHANGED = 'frsc'
|
||||
};
|
||||
@@ -144,6 +149,38 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* message)
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_THREAD_ADDED:
|
||||
{
|
||||
int32 threadID;
|
||||
if (message->FindInt32("thread", &threadID) == B_OK)
|
||||
_HandleThreadAdded(threadID);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_THREAD_REMOVED:
|
||||
{
|
||||
int32 threadID;
|
||||
if (message->FindInt32("thread", &threadID) == B_OK)
|
||||
_HandleThreadRemoved(threadID);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_THREAD_STATE_CHANGED:
|
||||
{
|
||||
int32 threadID;
|
||||
if (message->FindInt32("thread", &threadID) == B_OK)
|
||||
_HandleThreadStateChanged(threadID);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_THREAD_STACK_TRACE_CHANGED:
|
||||
{
|
||||
int32 threadID;
|
||||
if (message->FindInt32("thread", &threadID) == B_OK)
|
||||
_HandleThreadStackTraceChanged(threadID);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
break;
|
||||
@@ -152,6 +189,43 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* message)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionEvaluationWindow::ThreadAdded(const Team::ThreadEvent& event)
|
||||
{
|
||||
BMessage message(MSG_THREAD_ADDED);
|
||||
message.AddInt32("thread", event.GetThread()->ID());
|
||||
PostMessage(&message);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionEvaluationWindow::ThreadRemoved(const Team::ThreadEvent& event)
|
||||
{
|
||||
BMessage message(MSG_THREAD_REMOVED);
|
||||
message.AddInt32("thread", event.GetThread()->ID());
|
||||
PostMessage(&message);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionEvaluationWindow::ThreadStateChanged(const Team::ThreadEvent& event)
|
||||
{
|
||||
BMessage message(MSG_THREAD_STATE_CHANGED);
|
||||
message.AddInt32("thread", event.GetThread()->ID());
|
||||
PostMessage(&message);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionEvaluationWindow::ThreadStackTraceChanged(
|
||||
const Team::ThreadEvent& event)
|
||||
{
|
||||
BMessage message(MSG_THREAD_STACK_TRACE_CHANGED);
|
||||
message.AddInt32("thread", event.GetThread()->ID());
|
||||
PostMessage(&message);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionEvaluationWindow::ValueNodeValueRequested(CpuState* cpuState,
|
||||
ValueNodeContainer* container, ValueNode* valueNode)
|
||||
@@ -240,6 +314,12 @@ ExpressionEvaluationWindow::_HandleThreadSelectionChanged(int32 threadID)
|
||||
fSelectedThread = fTeam->ThreadByID(threadID);
|
||||
if (fSelectedThread != NULL)
|
||||
fSelectedThread->AcquireReference();
|
||||
else if (fThreadList->Menu()->FindMarked() == NULL) {
|
||||
// if the selected thread was cleared due to a thread event
|
||||
// rather than user selection, we need to reset the marked item
|
||||
// to reflect the new state.
|
||||
fThreadList->Menu()->ItemAt(0)->SetMarked(true);
|
||||
}
|
||||
|
||||
_UpdateFrameList();
|
||||
|
||||
@@ -286,6 +366,93 @@ ExpressionEvaluationWindow::_HandleFrameSelectionChanged(int32 index)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionEvaluationWindow::_HandleThreadAdded(int32 threadID)
|
||||
{
|
||||
AutoLocker< ::Team> teamLocker(fTeam);
|
||||
::Thread* thread = fTeam->ThreadByID(threadID);
|
||||
if (thread == NULL)
|
||||
return;
|
||||
|
||||
if (thread->State() != THREAD_STATE_STOPPED)
|
||||
return;
|
||||
|
||||
BMenuItem* item = NULL;
|
||||
if (_CreateThreadMenuItem(thread, item) != B_OK)
|
||||
return;
|
||||
|
||||
BMenu* threadMenu = fThreadList->Menu();
|
||||
int32 index = 1;
|
||||
// find appropriate insertion index to keep menu sorted in thread order.
|
||||
for (; index < threadMenu->CountItems(); index++) {
|
||||
BMenuItem* threadItem = threadMenu->ItemAt(index);
|
||||
BMessage* message = threadItem->Message();
|
||||
if (message->FindInt32("thread") > threadID)
|
||||
break;
|
||||
}
|
||||
|
||||
bool added = false;
|
||||
if (index == threadMenu->CountItems())
|
||||
added = threadMenu->AddItem(item);
|
||||
else
|
||||
added = threadMenu->AddItem(item, index);
|
||||
|
||||
if (!added)
|
||||
delete item;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionEvaluationWindow::_HandleThreadRemoved(int32 threadID)
|
||||
{
|
||||
BMenu* threadMenu = fThreadList->Menu();
|
||||
for (int32 i = 0; i < threadMenu->CountItems(); i++) {
|
||||
BMenuItem* item = threadMenu->ItemAt(i);
|
||||
BMessage* message = item->Message();
|
||||
if (message->FindInt32("thread") == threadID) {
|
||||
threadMenu->RemoveItem(i);
|
||||
delete item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fSelectedThread != NULL && threadID == fSelectedThread->ID())
|
||||
_HandleThreadSelectionChanged(-1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionEvaluationWindow::_HandleThreadStateChanged(int32 threadID)
|
||||
{
|
||||
AutoLocker< ::Team> teamLocker(fTeam);
|
||||
|
||||
::Thread* thread = fTeam->ThreadByID(threadID);
|
||||
if (thread == NULL)
|
||||
return;
|
||||
|
||||
if (thread->State() == THREAD_STATE_STOPPED)
|
||||
_HandleThreadAdded(threadID);
|
||||
else
|
||||
_HandleThreadRemoved(threadID);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionEvaluationWindow::_HandleThreadStackTraceChanged(int32 threadID)
|
||||
{
|
||||
AutoLocker< ::Team> teamLocker(fTeam);
|
||||
|
||||
::Thread* thread = fTeam->ThreadByID(threadID);
|
||||
if (thread == NULL)
|
||||
return;
|
||||
|
||||
if (thread != fSelectedThread)
|
||||
return;
|
||||
|
||||
_UpdateFrameList();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpressionEvaluationWindow::_UpdateThreadList()
|
||||
{
|
||||
@@ -305,25 +472,15 @@ ExpressionEvaluationWindow::_UpdateThreadList()
|
||||
if (thread->State() != THREAD_STATE_STOPPED)
|
||||
continue;
|
||||
|
||||
BString nameString;
|
||||
nameString.SetToFormat("%" B_PRId32 ": %s", thread->ID(),
|
||||
thread->Name());
|
||||
|
||||
BMessage* message = new(std::nothrow) BMessage(
|
||||
MSG_THREAD_SELECTION_CHANGED);
|
||||
if (message == NULL)
|
||||
return;
|
||||
|
||||
message->AddInt32("thread", thread->ID());
|
||||
|
||||
BMenuItem* item = new(std::nothrow) BMenuItem(nameString,
|
||||
message);
|
||||
if (item == NULL)
|
||||
BMenuItem* item = NULL;
|
||||
if (_CreateThreadMenuItem(thread, item) != B_OK)
|
||||
return;
|
||||
|
||||
ObjectDeleter<BMenuItem> itemDeleter(item);
|
||||
if (!threadMenu->AddItem(item))
|
||||
return;
|
||||
|
||||
itemDeleter.Detach();
|
||||
if (fSelectedThread == NULL) {
|
||||
item->SetMarked(true);
|
||||
_HandleThreadSelectionChanged(thread->ID());
|
||||
@@ -380,3 +537,28 @@ ExpressionEvaluationWindow::_UpdateFrameList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ExpressionEvaluationWindow::_CreateThreadMenuItem(::Thread* thread,
|
||||
BMenuItem*& _item) const
|
||||
{
|
||||
BString nameString;
|
||||
nameString.SetToFormat("%" B_PRId32 ": %s", thread->ID(),
|
||||
thread->Name());
|
||||
|
||||
BMessage* message = new(std::nothrow) BMessage(
|
||||
MSG_THREAD_SELECTION_CHANGED);
|
||||
if (message == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
ObjectDeleter<BMessage> messageDeleter(message);
|
||||
message->AddInt32("thread", thread->ID());
|
||||
_item = new(std::nothrow) BMenuItem(nameString,
|
||||
message);
|
||||
if (_item == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
messageDeleter.Detach();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
+18
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015, Rene Gollent, [email protected].
|
||||
* Copyright 2014-2016, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef EXPRESSION_EVALUATION_WINDOW_H
|
||||
@@ -41,6 +41,15 @@ public:
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
// Team::Listener
|
||||
virtual void ThreadAdded(const Team::ThreadEvent& event);
|
||||
virtual void ThreadRemoved(const Team::ThreadEvent& event);
|
||||
|
||||
virtual void ThreadStateChanged(
|
||||
const Team::ThreadEvent& event);
|
||||
virtual void ThreadStackTraceChanged(
|
||||
const Team::ThreadEvent& event);
|
||||
|
||||
// VariablesView::Listener
|
||||
virtual void ValueNodeValueRequested(CpuState* cpuState,
|
||||
ValueNodeContainer* container,
|
||||
@@ -62,9 +71,17 @@ private:
|
||||
void _HandleThreadSelectionChanged(int32 threadID);
|
||||
void _HandleFrameSelectionChanged(int32 index);
|
||||
|
||||
void _HandleThreadAdded(int32 threadID);
|
||||
void _HandleThreadRemoved(int32 threadID);
|
||||
void _HandleThreadStateChanged(int32 threadID);
|
||||
void _HandleThreadStackTraceChanged(int32 threadID);
|
||||
|
||||
void _UpdateThreadList();
|
||||
void _UpdateFrameList();
|
||||
|
||||
status_t _CreateThreadMenuItem(::Thread* thread,
|
||||
BMenuItem*& _item) const;
|
||||
|
||||
private:
|
||||
BTextControl* fExpressionInput;
|
||||
BMenuField* fThreadList;
|
||||
|
||||
Reference in New Issue
Block a user