* Added notifications for thread state/CPU state/stack trace changes. The team

window listens for those and updates the buttons correctly.
* Added basic handling for the thread stopping debug events in the team
  debugger.
* Forward the thread run/stop/step requests to the team debugger and actually
  run/stop/step the thread. Running/stopping works, all three stepping actions
  just step by a single instruction ATM, though.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31107 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-06-18 21:45:14 +00:00
parent 18882afba2
commit b6aff5aa83
10 changed files with 371 additions and 22 deletions

View File

@ -7,10 +7,15 @@
enum { enum {
MSG_THREAD_RUN = 'run_', MSG_THREAD_RUN = 'run_',
MSG_THREAD_STEP_OVER = 'stov', MSG_THREAD_STOP = 'stop',
MSG_THREAD_STEP_INTO = 'stin', MSG_THREAD_STEP_OVER = 'stov',
MSG_THREAD_STEP_OUT = 'stou' MSG_THREAD_STEP_INTO = 'stin',
MSG_THREAD_STEP_OUT = 'stou',
MSG_THREAD_STATE_CHANGED = 'tsch',
MSG_THREAD_CPU_STATE_CHANGED = 'tcsc',
MSG_THREAD_STACK_TRACE_CHANGED = 'tstc'
}; };

View File

@ -204,6 +204,39 @@ Team::RemoveListener(Listener* listener)
} }
void
Team::NotifyThreadStateChanged(Thread* thread)
{
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {
listener->ThreadStateChanged(
ThreadEvent(TEAM_EVENT_THREAD_STATE_CHANGED, thread));
}
}
void
Team::NotifyThreadCpuStateChanged(Thread* thread)
{
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {
listener->ThreadCpuStateChanged(
ThreadEvent(TEAM_EVENT_THREAD_CPU_STATE_CHANGED, thread));
}
}
void
Team::NotifyThreadStackTraceChanged(Thread* thread)
{
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {
listener->ThreadStackTraceChanged(
ThreadEvent(TEAM_EVENT_THREAD_STACK_TRACE_CHANGED, thread));
}
}
void void
Team::_NotifyThreadAdded(Thread* thread) Team::_NotifyThreadAdded(Thread* thread)
{ {
@ -307,3 +340,21 @@ void
Team::Listener::ImageRemoved(const Team::ImageEvent& event) Team::Listener::ImageRemoved(const Team::ImageEvent& event)
{ {
} }
void
Team::Listener::ThreadStateChanged(const Team::ThreadEvent& event)
{
}
void
Team::Listener::ThreadCpuStateChanged(const Team::ThreadEvent& event)
{
}
void
Team::Listener::ThreadStackTraceChanged(const Team::ThreadEvent& event)
{
}

View File

@ -18,7 +18,11 @@ enum {
TEAM_EVENT_THREAD_ADDED, TEAM_EVENT_THREAD_ADDED,
TEAM_EVENT_THREAD_REMOVED, TEAM_EVENT_THREAD_REMOVED,
TEAM_EVENT_IMAGE_ADDED, TEAM_EVENT_IMAGE_ADDED,
TEAM_EVENT_IMAGE_REMOVED TEAM_EVENT_IMAGE_REMOVED,
TEAM_EVENT_THREAD_STATE_CHANGED,
TEAM_EVENT_THREAD_CPU_STATE_CHANGED,
TEAM_EVENT_THREAD_STACK_TRACE_CHANGED
}; };
@ -59,6 +63,11 @@ public:
void AddListener(Listener* listener); void AddListener(Listener* listener);
void RemoveListener(Listener* listener); void RemoveListener(Listener* listener);
// service methods for Thread
void NotifyThreadStateChanged(Thread* thread);
void NotifyThreadCpuStateChanged(Thread* thread);
void NotifyThreadStackTraceChanged(Thread* thread);
private: private:
typedef DoublyLinkedList<Listener> ListenerList; typedef DoublyLinkedList<Listener> ListenerList;
@ -121,6 +130,13 @@ public:
virtual void ImageAdded(const Team::ImageEvent& event); virtual void ImageAdded(const Team::ImageEvent& event);
virtual void ImageRemoved(const Team::ImageEvent& event); virtual void ImageRemoved(const Team::ImageEvent& event);
virtual void ThreadStateChanged(
const Team::ThreadEvent& event);
virtual void ThreadCpuStateChanged(
const Team::ThreadEvent& event);
virtual void ThreadStackTraceChanged(
const Team::ThreadEvent& event);
}; };

View File

@ -17,6 +17,7 @@
#include "CpuState.h" #include "CpuState.h"
#include "DebuggerInterface.h" #include "DebuggerInterface.h"
#include "MessageCodes.h"
#include "Team.h" #include "Team.h"
#include "TeamDebugModel.h" #include "TeamDebugModel.h"
@ -168,6 +169,19 @@ void
TeamDebugger::MessageReceived(BMessage* message) TeamDebugger::MessageReceived(BMessage* message)
{ {
switch (message->what) { switch (message->what) {
case MSG_THREAD_RUN:
case MSG_THREAD_STOP:
case MSG_THREAD_STEP_OVER:
case MSG_THREAD_STEP_INTO:
case MSG_THREAD_STEP_OUT:
{
int32 threadID;
if (message->FindInt32("thread", &threadID) != B_OK)
break;
_HandleThreadAction(threadID, message->what);
break;
}
default: default:
BLooper::MessageReceived(message); BLooper::MessageReceived(message);
break; break;
@ -175,6 +189,24 @@ TeamDebugger::MessageReceived(BMessage* message)
} }
void
TeamDebugger::ThreadActionRequested(TeamWindow* window, thread_id threadID,
uint32 action)
{
BMessage message(action);
message.AddInt32("thread", threadID);
PostMessage(&message);
}
bool
TeamDebugger::TeamWindowQuitRequested(TeamWindow* window)
{
// TODO:...
return true;
}
/*static*/ status_t /*static*/ status_t
TeamDebugger::_DebugEventListenerEntry(void* data) TeamDebugger::_DebugEventListenerEntry(void* data)
{ {
@ -222,30 +254,43 @@ printf("TeamDebugger::_HandleDebuggerMessage(): %d\n", event->EventType());
switch (event->EventType()) { switch (event->EventType()) {
case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED:
printf("B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: thread: %ld\n", event->Thread()); printf("B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: thread: %ld\n", event->Thread());
handled = _HandleThreadDebugged(
dynamic_cast<ThreadDebuggedEvent*>(event));
break; break;
case B_DEBUGGER_MESSAGE_DEBUGGER_CALL: case B_DEBUGGER_MESSAGE_DEBUGGER_CALL:
printf("B_DEBUGGER_MESSAGE_DEBUGGER_CALL: thread: %ld\n", event->Thread()); printf("B_DEBUGGER_MESSAGE_DEBUGGER_CALL: thread: %ld\n", event->Thread());
handled = _HandleDebuggerCall(
dynamic_cast<DebuggerCallEvent*>(event));
break; break;
case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT:
printf("B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: thread: %ld\n", event->Thread()); printf("B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: thread: %ld\n", event->Thread());
handled = _HandleBreakpointHit(
dynamic_cast<BreakpointHitEvent*>(event));
break; break;
case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT:
printf("B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: thread: %ld\n", event->Thread()); printf("B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: thread: %ld\n", event->Thread());
handled = _HandleWatchpointHit(
dynamic_cast<WatchpointHitEvent*>(event));
break; break;
case B_DEBUGGER_MESSAGE_SINGLE_STEP: case B_DEBUGGER_MESSAGE_SINGLE_STEP:
printf("B_DEBUGGER_MESSAGE_SINGLE_STEP: thread: %ld\n", event->Thread()); printf("B_DEBUGGER_MESSAGE_SINGLE_STEP: thread: %ld\n", event->Thread());
handled = _HandleSingleStep(dynamic_cast<SingleStepEvent*>(event));
break; break;
case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED:
printf("B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: thread: %ld\n", event->Thread()); printf("B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: thread: %ld\n", event->Thread());
handled = _HandleExceptionOccurred(
dynamic_cast<ExceptionOccurredEvent*>(event));
break; break;
// case B_DEBUGGER_MESSAGE_TEAM_CREATED: // case B_DEBUGGER_MESSAGE_TEAM_CREATED:
//printf("B_DEBUGGER_MESSAGE_TEAM_CREATED: team: %ld\n", message.team_created.new_team); //printf("B_DEBUGGER_MESSAGE_TEAM_CREATED: team: %ld\n", message.team_created.new_team);
// break; // break;
case B_DEBUGGER_MESSAGE_TEAM_DELETED: case B_DEBUGGER_MESSAGE_TEAM_DELETED:
// TODO: Handle!
printf("B_DEBUGGER_MESSAGE_TEAM_DELETED: team: %ld\n", event->Team()); printf("B_DEBUGGER_MESSAGE_TEAM_DELETED: team: %ld\n", event->Team());
break; break;
case B_DEBUGGER_MESSAGE_TEAM_EXEC: case B_DEBUGGER_MESSAGE_TEAM_EXEC:
printf("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %ld\n", event->Team()); printf("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %ld\n", event->Team());
// TODO: Handle!
break; break;
case B_DEBUGGER_MESSAGE_THREAD_CREATED: case B_DEBUGGER_MESSAGE_THREAD_CREATED:
handled = _HandleThreadCreated( handled = _HandleThreadCreated(
@ -281,6 +326,70 @@ printf("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %ld\n", event->Team());
} }
bool
TeamDebugger::_HandleThreadStopped(thread_id threadID, CpuState* cpuState)
{
// get the thread
AutoLocker< ::Team> locker(fTeam);
::Thread* thread = fTeam->ThreadByID(threadID);
if (thread == NULL)
return false;
// update the thread state
thread->SetState(THREAD_STATE_STOPPED);
if (cpuState != NULL) {
thread->SetCpuState(cpuState);
} else {
// TODO: Trigger updating the CPU state!
}
return true;
}
bool
TeamDebugger::_HandleThreadDebugged(ThreadDebuggedEvent* event)
{
return _HandleThreadStopped(event->Thread(), NULL);
}
bool
TeamDebugger::_HandleDebuggerCall(DebuggerCallEvent* event)
{
return _HandleThreadStopped(event->Thread(), NULL);
}
bool
TeamDebugger::_HandleBreakpointHit(BreakpointHitEvent* event)
{
return _HandleThreadStopped(event->Thread(), event->GetCpuState());
}
bool
TeamDebugger::_HandleWatchpointHit(WatchpointHitEvent* event)
{
return _HandleThreadStopped(event->Thread(), event->GetCpuState());
}
bool
TeamDebugger::_HandleSingleStep(SingleStepEvent* event)
{
return _HandleThreadStopped(event->Thread(), event->GetCpuState());
}
bool
TeamDebugger::_HandleExceptionOccurred(ExceptionOccurredEvent* event)
{
return _HandleThreadStopped(event->Thread(), NULL);
}
bool bool
TeamDebugger::_HandleThreadCreated(ThreadCreatedEvent* event) TeamDebugger::_HandleThreadCreated(ThreadCreatedEvent* event)
{ {
@ -339,3 +448,53 @@ TeamDebugger::_UpdateThreadState(::Thread* thread)
thread->SetState(newState); thread->SetState(newState);
thread->SetCpuState(state); thread->SetCpuState(state);
} }
void
TeamDebugger::_HandleThreadAction(thread_id threadID, uint32 action)
{
AutoLocker< ::Team> locker(fTeam);
::Thread* thread = fTeam->ThreadByID(threadID);
if (thread == NULL || thread->State() == THREAD_STATE_UNKNOWN)
return;
// When stop is requested, thread must be running, otherwise stopped.
if (action == MSG_THREAD_STOP
? thread->State() != THREAD_STATE_RUNNING
: thread->State() != THREAD_STATE_STOPPED) {
return;
}
// When continuing the thread update thread state before actually issuing
// the command, since we need to unlock.
if (action != MSG_THREAD_STOP)
thread->SetState(THREAD_STATE_RUNNING);
locker.Unlock();
switch (action) {
case MSG_THREAD_RUN:
printf("MSG_THREAD_RUN\n");
fDebuggerInterface->ContinueThread(threadID);
break;
case MSG_THREAD_STOP:
printf("MSG_THREAD_STOP\n");
fDebuggerInterface->StopThread(threadID);
break;
case MSG_THREAD_STEP_OVER:
printf("MSG_THREAD_STEP_OVER\n");
fDebuggerInterface->SingleStepThread(threadID);
break;
case MSG_THREAD_STEP_INTO:
printf("MSG_THREAD_STEP_INTO\n");
fDebuggerInterface->SingleStepThread(threadID);
break;
case MSG_THREAD_STEP_OUT:
printf("MSG_THREAD_STEP_OUT\n");
fDebuggerInterface->SingleStepThread(threadID);
break;
// TODO: Handle stepping correctly!
}
}

View File

@ -34,12 +34,32 @@ public:
private: private:
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
// TeamWindow::Listener
virtual void ThreadActionRequested(TeamWindow* window,
thread_id threadID, uint32 action);
virtual bool TeamWindowQuitRequested(TeamWindow* window);
private: private:
static status_t _DebugEventListenerEntry(void* data); static status_t _DebugEventListenerEntry(void* data);
status_t _DebugEventListener(); status_t _DebugEventListener();
void _HandleDebuggerMessage(DebugEvent* event); void _HandleDebuggerMessage(DebugEvent* event);
bool _HandleThreadStopped(thread_id threadID,
CpuState* cpuState);
bool _HandleThreadDebugged(
ThreadDebuggedEvent* event);
bool _HandleDebuggerCall(
DebuggerCallEvent* event);
bool _HandleBreakpointHit(
BreakpointHitEvent* event);
bool _HandleWatchpointHit(
WatchpointHitEvent* event);
bool _HandleSingleStep(
SingleStepEvent* event);
bool _HandleExceptionOccurred(
ExceptionOccurredEvent* event);
bool _HandleThreadCreated( bool _HandleThreadCreated(
ThreadCreatedEvent* event); ThreadCreatedEvent* event);
bool _HandleThreadDeleted( bool _HandleThreadDeleted(
@ -51,6 +71,9 @@ private:
void _UpdateThreadState(::Thread* thread); void _UpdateThreadState(::Thread* thread);
void _HandleThreadAction(thread_id threadID,
uint32 action);
private: private:
::Team* fTeam; ::Team* fTeam;
TeamDebugModel* fDebugModel; TeamDebugModel* fDebugModel;

View File

@ -7,6 +7,7 @@
#include "CpuState.h" #include "CpuState.h"
#include "StackTrace.h" #include "StackTrace.h"
#include "Team.h"
Thread::Thread(Team* team, thread_id threadID) Thread::Thread(Team* team, thread_id threadID)
@ -56,6 +57,8 @@ Thread::SetState(uint32 state)
SetCpuState(NULL); SetCpuState(NULL);
SetStackTrace(NULL); SetStackTrace(NULL);
} }
fTeam->NotifyThreadStateChanged(this);
} }
@ -72,8 +75,11 @@ Thread::SetCpuState(CpuState* state)
if (fCpuState != NULL) if (fCpuState != NULL)
fCpuState->AddReference(); fCpuState->AddReference();
fTeam->NotifyThreadCpuStateChanged(this);
} }
void void
Thread::SetStackTrace(StackTrace* trace) Thread::SetStackTrace(StackTrace* trace)
{ {
@ -87,4 +93,6 @@ Thread::SetStackTrace(StackTrace* trace)
if (fStackTrace != NULL) if (fStackTrace != NULL)
fStackTrace->AddReference(); fStackTrace->AddReference();
fTeam->NotifyThreadStackTraceChanged(this);
} }

View File

@ -131,6 +131,26 @@ DebuggerInterface::ContinueThread(thread_id thread)
} }
status_t
DebuggerInterface::StopThread(thread_id thread)
{
return debug_thread(thread);
}
status_t
DebuggerInterface::SingleStepThread(thread_id thread)
{
debug_nub_continue_thread continueMessage;
continueMessage.thread = thread;
continueMessage.handle_event = B_THREAD_DEBUG_HANDLE_EVENT;
continueMessage.single_step = true;
return write_port(fNubPort, B_DEBUG_MESSAGE_CONTINUE_THREAD,
&continueMessage, sizeof(continueMessage));
}
status_t status_t
DebuggerInterface::GetThreadInfos(BObjectList<ThreadInfo>& infos) DebuggerInterface::GetThreadInfos(BObjectList<ThreadInfo>& infos)
{ {

View File

@ -34,6 +34,8 @@ public:
virtual status_t SetTeamDebuggingFlags(uint32 flags); virtual status_t SetTeamDebuggingFlags(uint32 flags);
virtual status_t ContinueThread(thread_id thread); virtual status_t ContinueThread(thread_id thread);
virtual status_t StopThread(thread_id thread);
virtual status_t SingleStepThread(thread_id thread);
virtual status_t GetThreadInfos(BObjectList<ThreadInfo>& infos); virtual status_t GetThreadInfos(BObjectList<ThreadInfo>& infos);
virtual status_t GetImageInfos(BObjectList<ImageInfo>& infos); virtual status_t GetImageInfos(BObjectList<ImageInfo>& infos);

View File

@ -14,6 +14,8 @@
#include <SplitView.h> #include <SplitView.h>
#include <TextView.h> #include <TextView.h>
#include <AutoLocker.h>
#include "ImageListView.h" #include "ImageListView.h"
#include "MessageCodes.h" #include "MessageCodes.h"
#include "TeamDebugModel.h" #include "TeamDebugModel.h"
@ -42,11 +44,14 @@ TeamWindow::TeamWindow(TeamDebugModel* debugModel, Listener* listener)
if (team->ID() >= 0) if (team->ID() >= 0)
name << " (" << team->ID() << ")"; name << " (" << team->ID() << ")";
SetTitle(name.String()); SetTitle(name.String());
team->AddListener(this);
} }
TeamWindow::~TeamWindow() TeamWindow::~TeamWindow()
{ {
fDebugModel->GetTeam()->RemoveListener(this);
} }
@ -71,17 +76,28 @@ TeamWindow::MessageReceived(BMessage* message)
{ {
switch (message->what) { switch (message->what) {
case MSG_THREAD_RUN: case MSG_THREAD_RUN:
printf("MSG_THREAD_RUN\n"); case MSG_THREAD_STOP:
break;
case MSG_THREAD_STEP_OVER: case MSG_THREAD_STEP_OVER:
printf("MSG_THREAD_STEP_OVER\n");
break;
case MSG_THREAD_STEP_INTO: case MSG_THREAD_STEP_INTO:
printf("MSG_THREAD_STEP_INTO\n");
break;
case MSG_THREAD_STEP_OUT: case MSG_THREAD_STEP_OUT:
printf("MSG_THREAD_STEP_OUT\n"); if (fActiveThread != NULL) {
fListener->ThreadActionRequested(this, fActiveThread->ID(),
message->what);
}
break; break;
case MSG_THREAD_STATE_CHANGED:
{
int32 threadID;
if (message->FindInt32("thread", &threadID) != B_OK)
break;
_HandleThreadStateChanged(threadID);
break;
}
// case MSG_THREAD_CPU_STATE_CHANGED:
// case MSG_THREAD_STACK_TRACE_CHANGED:
default: default:
BWindow::MessageReceived(message); BWindow::MessageReceived(message);
break; break;
@ -103,6 +119,33 @@ TeamWindow::ThreadSelectionChanged(::Thread* thread)
} }
void
TeamWindow::ThreadStateChanged(const Team::ThreadEvent& event)
{
BMessage message(MSG_THREAD_STATE_CHANGED);
message.AddInt32("thread", event.GetThread()->ID());
PostMessage(&message);
}
void
TeamWindow::ThreadCpuStateChanged(const Team::ThreadEvent& event)
{
// BMessage message(MSG_THREAD_CPU_STATE_CHANGED);
// message.AddInt32("thread", event.GetThread()->ID());
// PostMessage(&message);
}
void
TeamWindow::ThreadStackTraceChanged(const Team::ThreadEvent& event)
{
// BMessage message(MSG_THREAD_STACK_TRACE_CHANGED);
// message.AddInt32("thread", event.GetThread()->ID());
// PostMessage(&message);
}
void void
TeamWindow::_Init() TeamWindow::_Init()
{ {
@ -155,6 +198,7 @@ TeamWindow::_Init()
fRunButton->SetTarget(this); fRunButton->SetTarget(this);
fStepOutButton->SetTarget(this); fStepOutButton->SetTarget(this);
AutoLocker<TeamDebugModel> locker(fDebugModel);
_UpdateRunButtons(); _UpdateRunButtons();
} }
@ -167,6 +211,7 @@ TeamWindow::_SetActiveThread(::Thread* thread)
fActiveThread = thread; fActiveThread = thread;
AutoLocker<TeamDebugModel> locker(fDebugModel);
_UpdateRunButtons(); _UpdateRunButtons();
} }
@ -186,6 +231,7 @@ TeamWindow::_UpdateRunButtons()
break; break;
case THREAD_STATE_RUNNING: case THREAD_STATE_RUNNING:
fRunButton->SetLabel("Stop"); fRunButton->SetLabel("Stop");
fRunButton->SetMessage(new BMessage(MSG_THREAD_STOP));
fRunButton->SetEnabled(true); fRunButton->SetEnabled(true);
fStepOverButton->SetEnabled(false); fStepOverButton->SetEnabled(false);
fStepIntoButton->SetEnabled(false); fStepIntoButton->SetEnabled(false);
@ -193,6 +239,7 @@ TeamWindow::_UpdateRunButtons()
break; break;
case THREAD_STATE_STOPPED: case THREAD_STATE_STOPPED:
fRunButton->SetLabel("Run"); fRunButton->SetLabel("Run");
fRunButton->SetMessage(new BMessage(MSG_THREAD_RUN));
fRunButton->SetEnabled(true); fRunButton->SetEnabled(true);
fStepOverButton->SetEnabled(true); fStepOverButton->SetEnabled(true);
fStepIntoButton->SetEnabled(true); fStepIntoButton->SetEnabled(true);
@ -202,16 +249,21 @@ TeamWindow::_UpdateRunButtons()
} }
void
TeamWindow::_HandleThreadStateChanged(thread_id threadID)
{
// ATM we're only interested in the currently selected thread
if (fActiveThread == NULL || threadID != fActiveThread->ID())
return;
AutoLocker<TeamDebugModel> locker(fDebugModel);
_UpdateRunButtons();
}
// #pragma mark - Listener // #pragma mark - Listener
TeamWindow::Listener::~Listener() TeamWindow::Listener::~Listener()
{ {
} }
bool
TeamWindow::Listener::TeamWindowQuitRequested(TeamWindow* window)
{
return true;
}

View File

@ -8,17 +8,18 @@
#include <String.h> #include <String.h>
#include <Window.h> #include <Window.h>
#include "Team.h"
#include "ThreadListView.h" #include "ThreadListView.h"
class BButton; class BButton;
class BTabView; class BTabView;
class ImageListView; class ImageListView;
class Team;
class TeamDebugModel; class TeamDebugModel;
class TeamWindow : public BWindow, private ThreadListView::Listener { class TeamWindow : public BWindow, private ThreadListView::Listener,
Team::Listener {
public: public:
class Listener; class Listener;
@ -38,11 +39,21 @@ private:
// ThreadListView::Listener // ThreadListView::Listener
virtual void ThreadSelectionChanged(::Thread* thread); virtual void ThreadSelectionChanged(::Thread* thread);
// Team::Listener
virtual void ThreadStateChanged(
const Team::ThreadEvent& event);
virtual void ThreadCpuStateChanged(
const Team::ThreadEvent& event);
virtual void ThreadStackTraceChanged(
const Team::ThreadEvent& event);
void _Init(); void _Init();
void _SetActiveThread(::Thread* thread); void _SetActiveThread(::Thread* thread);
void _UpdateRunButtons(); void _UpdateRunButtons();
void _HandleThreadStateChanged(thread_id threadID);
private: private:
TeamDebugModel* fDebugModel; TeamDebugModel* fDebugModel;
::Thread* fActiveThread; ::Thread* fActiveThread;
@ -61,7 +72,9 @@ class TeamWindow::Listener {
public: public:
virtual ~Listener(); virtual ~Listener();
virtual bool TeamWindowQuitRequested(TeamWindow* window); virtual void ThreadActionRequested(TeamWindow* window,
thread_id threadID, uint32 action) = 0;
virtual bool TeamWindowQuitRequested(TeamWindow* window) = 0;
}; };