Finally integrates running_teams_window stuff to the Debugger app:
* Rework Debugger class a bit to ease integration * Expand TeamDebugger::Listener interface to notify start event too. * Former RunningTeamsWindow, now name TeamsWindow, is shown at start if no team/program to launch is specified. * Double-clicking a team item in this list starts a new Team debugger, or reactivate the existing one if any This window settings is not yet integrated with the SettingsManager. Will comes next. I plan to add some UI controls to this Teams window to allow user to setup a program arguments and environment variables and then launch & debug it. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38758 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+279
-173
@@ -23,6 +23,7 @@
|
|||||||
#include "MessageCodes.h"
|
#include "MessageCodes.h"
|
||||||
#include "SettingsManager.h"
|
#include "SettingsManager.h"
|
||||||
#include "TeamDebugger.h"
|
#include "TeamDebugger.h"
|
||||||
|
#include "TeamsWindow.h"
|
||||||
#include "TypeHandlerRoster.h"
|
#include "TypeHandlerRoster.h"
|
||||||
#include "ValueHandlerRoster.h"
|
#include "ValueHandlerRoster.h"
|
||||||
|
|
||||||
@@ -153,12 +154,16 @@ parse_arguments(int argc, const char* const* argv, bool noOutput,
|
|||||||
exclusiveParams++;
|
exclusiveParams++;
|
||||||
|
|
||||||
if (exclusiveParams == 0) {
|
if (exclusiveParams == 0) {
|
||||||
|
|
||||||
|
/*
|
||||||
// TODO: Support!
|
// TODO: Support!
|
||||||
if (noOutput)
|
if (noOutput)
|
||||||
return false;
|
return false;
|
||||||
fprintf(stderr, "Sorry, running without team/thread to debug not "
|
fprintf(stderr, "Sorry, running without team/thread to debug not "
|
||||||
"supported yet.\n");
|
"supported yet.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
} else if (exclusiveParams != 1) {
|
} else if (exclusiveParams != 1) {
|
||||||
if (noOutput)
|
if (noOutput)
|
||||||
return false;
|
return false;
|
||||||
@@ -169,197 +174,298 @@ parse_arguments(int argc, const char* const* argv, bool noOutput,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
class Debugger : public BApplication, private TeamDebugger::Listener {
|
class Debugger : public BApplication, private TeamDebugger::Listener {
|
||||||
public:
|
public:
|
||||||
Debugger()
|
Debugger();
|
||||||
:
|
~Debugger();
|
||||||
BApplication(kDebuggerSignature),
|
|
||||||
fRunningTeamDebuggers(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~Debugger()
|
status_t Init();
|
||||||
{
|
virtual void MessageReceived(BMessage* message);
|
||||||
ValueHandlerRoster::DeleteDefault();
|
virtual void ReadyToRun();
|
||||||
TypeHandlerRoster::DeleteDefault();
|
virtual void ArgvReceived(int32 argc, char** argv);
|
||||||
}
|
|
||||||
|
|
||||||
status_t Init()
|
|
||||||
{
|
|
||||||
status_t error = TypeHandlerRoster::CreateDefault();
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
error = ValueHandlerRoster::CreateDefault();
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
return fSettingsManager.Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage* message)
|
|
||||||
{
|
|
||||||
switch (message->what) {
|
|
||||||
case MSG_TEAM_DEBUGGER_QUIT:
|
|
||||||
{
|
|
||||||
int32 threadID;
|
|
||||||
if (message->FindInt32("thread", &threadID) == B_OK)
|
|
||||||
wait_for_thread(threadID, NULL);
|
|
||||||
|
|
||||||
if (--fRunningTeamDebuggers == 0)
|
|
||||||
Quit();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
BApplication::MessageReceived(message);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void ReadyToRun()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void ArgvReceived(int32 argc, char** argv)
|
|
||||||
{
|
|
||||||
Options options;
|
|
||||||
if (!parse_arguments(argc, argv, true, options))
|
|
||||||
{
|
|
||||||
printf("Debugger::ArgvReceived(): parsing args failed!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
team_id team = options.team;
|
|
||||||
thread_id thread = options.thread;
|
|
||||||
bool stopInMain = false;
|
|
||||||
|
|
||||||
// If command line arguments were given, start the program.
|
|
||||||
if (options.commandLineArgc > 0) {
|
|
||||||
printf("loading program: \"%s\" ...\n", options.commandLineArgv[0]);
|
|
||||||
// TODO: What about the CWD?
|
|
||||||
thread = load_program(options.commandLineArgv,
|
|
||||||
options.commandLineArgc, false);
|
|
||||||
if (thread < 0) {
|
|
||||||
// TODO: Notify the user!
|
|
||||||
fprintf(stderr, "Error: Failed to load program \"%s\": %s\n",
|
|
||||||
options.commandLineArgv[0], strerror(thread));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
team = thread;
|
|
||||||
// main thread ID == team ID
|
|
||||||
stopInMain = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we've got
|
|
||||||
if (team < 0) {
|
|
||||||
printf("no team yet, getting thread info...\n");
|
|
||||||
thread_info threadInfo;
|
|
||||||
status_t error = get_thread_info(thread, &threadInfo);
|
|
||||||
if (error != B_OK) {
|
|
||||||
// TODO: Notify the user!
|
|
||||||
fprintf(stderr, "Error: Failed to get info for thread \"%ld\": "
|
|
||||||
"%s\n", thread, strerror(error));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
team = threadInfo.team;
|
|
||||||
}
|
|
||||||
printf("team: %ld, thread: %ld\n", team, thread);
|
|
||||||
|
|
||||||
TeamDebugger* debugger = _TeamDebuggerForTeam(team);
|
|
||||||
if (debugger != NULL) {
|
|
||||||
// TODO: Activate the respective window!
|
|
||||||
printf("There's already a debugger for team: %ld\n", team);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UserInterface* userInterface = new(std::nothrow) GraphicalUserInterface;
|
|
||||||
if (userInterface == NULL) {
|
|
||||||
// TODO: Notify the user!
|
|
||||||
fprintf(stderr, "Error: Out of memory!\n");
|
|
||||||
}
|
|
||||||
Reference<UserInterface> userInterfaceReference(userInterface, true);
|
|
||||||
|
|
||||||
debugger = new(std::nothrow) TeamDebugger(this, userInterface,
|
|
||||||
&fSettingsManager);
|
|
||||||
if (debugger == NULL) {
|
|
||||||
// TODO: Notify the user!
|
|
||||||
fprintf(stderr, "Error: Out of memory!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t error = debugger->Init(team, thread, stopInMain);
|
|
||||||
if (debugger->Thread())
|
|
||||||
fRunningTeamDebuggers++;
|
|
||||||
|
|
||||||
if (error == B_OK && fTeamDebuggers.AddItem(debugger)) {
|
|
||||||
printf("debugger for team %ld created and initialized successfully!\n", team);
|
|
||||||
} else
|
|
||||||
delete debugger;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef BObjectList<TeamDebugger> TeamDebuggerList;
|
typedef BObjectList<TeamDebugger> TeamDebuggerList;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// TeamDebugger::Listener
|
// TeamDebugger::Listener
|
||||||
virtual void TeamDebuggerQuit(TeamDebugger* debugger)
|
virtual void TeamDebuggerStarted(TeamDebugger* debugger);
|
||||||
{
|
virtual void TeamDebuggerQuit(TeamDebugger* debugger);
|
||||||
// Note: Locking here only works, since we're never locking the other
|
|
||||||
// way around. If we even need to do that, we'll have to introduce a
|
|
||||||
// separate lock to protect the list.
|
|
||||||
AutoLocker<Debugger> locker(this);
|
|
||||||
fTeamDebuggers.RemoveItem(debugger);
|
|
||||||
locker.Unlock();
|
|
||||||
|
|
||||||
if (debugger->Thread() >= 0) {
|
virtual bool QuitRequested();
|
||||||
BMessage message(MSG_TEAM_DEBUGGER_QUIT);
|
virtual void Quit();
|
||||||
message.AddInt32("thread", debugger->Thread());
|
|
||||||
PostMessage(&message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool QuitRequested()
|
|
||||||
{
|
|
||||||
// NOTE: The default implementation will just ask all windows'
|
|
||||||
// QuitRequested() hooks. This in turn will ask the TeamWindows.
|
|
||||||
// For now, this is what we want. If we have more windows later,
|
|
||||||
// like the global TeamsWindow, then we want to just ask the
|
|
||||||
// TeamDebuggers, the TeamsWindow should of course not go away already
|
|
||||||
// if one or more TeamDebuggers want to stay later. There are multiple
|
|
||||||
// ways how to do this. For examaple, TeamDebugger could get a
|
|
||||||
// QuitReqested() hook or the TeamsWindow and other global windows
|
|
||||||
// could always return false in their QuitRequested().
|
|
||||||
return BApplication::QuitRequested();
|
|
||||||
// TODO: This is ugly. The team debuggers own the windows, not the
|
|
||||||
// other way around.
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Quit()
|
|
||||||
{
|
|
||||||
// don't quit before all team debuggers have been quit
|
|
||||||
if (fRunningTeamDebuggers <= 0)
|
|
||||||
BApplication::Quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
TeamDebugger* _TeamDebuggerForTeam(team_id teamID) const
|
|
||||||
{
|
|
||||||
for (int32 i = 0; TeamDebugger* debugger = fTeamDebuggers.ItemAt(i);
|
|
||||||
i++) {
|
|
||||||
if (debugger->TeamID() == teamID)
|
|
||||||
return debugger;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
TeamDebugger* _FindTeamDebugger(team_id teamID) const;
|
||||||
|
TeamDebugger* _StartTeamDebugger(team_id teamID,
|
||||||
|
thread_id threadID = -1, bool stopInMain = false);
|
||||||
private:
|
private:
|
||||||
SettingsManager fSettingsManager;
|
SettingsManager fSettingsManager;
|
||||||
TeamDebuggerList fTeamDebuggers;
|
TeamDebuggerList fTeamDebuggers;
|
||||||
int32 fRunningTeamDebuggers;
|
int32 fRunningTeamDebuggers;
|
||||||
|
TeamsWindow* fTeamsWindow;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Debugger::Debugger()
|
||||||
|
:
|
||||||
|
BApplication(kDebuggerSignature),
|
||||||
|
fRunningTeamDebuggers(0),
|
||||||
|
fTeamsWindow(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Debugger::~Debugger()
|
||||||
|
{
|
||||||
|
ValueHandlerRoster::DeleteDefault();
|
||||||
|
TypeHandlerRoster::DeleteDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Debugger::Init()
|
||||||
|
{
|
||||||
|
status_t error = TypeHandlerRoster::CreateDefault();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
error = ValueHandlerRoster::CreateDefault();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
return fSettingsManager.Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Debugger::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case MSG_SHOW_TEAMS_WINDOW:
|
||||||
|
{
|
||||||
|
if (fTeamsWindow)
|
||||||
|
fTeamsWindow->Activate(true);
|
||||||
|
else {
|
||||||
|
fTeamsWindow = new TeamsWindow();
|
||||||
|
fTeamsWindow->Show();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MSG_TEAMS_WINDOW_CLOSED:
|
||||||
|
{
|
||||||
|
fTeamsWindow = NULL;
|
||||||
|
Quit();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MSG_DEBUG_THIS_TEAM:
|
||||||
|
{
|
||||||
|
int32 teamID;
|
||||||
|
if (message->FindInt32("team", &teamID) != B_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
_StartTeamDebugger(teamID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MSG_TEAM_DEBUGGER_QUIT:
|
||||||
|
{
|
||||||
|
int32 threadID;
|
||||||
|
if (message->FindInt32("thread", &threadID) == B_OK)
|
||||||
|
wait_for_thread(threadID, NULL);
|
||||||
|
|
||||||
|
--fRunningTeamDebuggers;
|
||||||
|
Quit();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
BApplication::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Debugger::ReadyToRun()
|
||||||
|
{
|
||||||
|
if (fRunningTeamDebuggers == 0)
|
||||||
|
PostMessage(MSG_SHOW_TEAMS_WINDOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Debugger::ArgvReceived(int32 argc, char** argv)
|
||||||
|
{
|
||||||
|
Options options;
|
||||||
|
if (!parse_arguments(argc, argv, true, options)) {
|
||||||
|
printf("Debugger::ArgvReceived(): parsing args failed!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
team_id team = options.team;
|
||||||
|
thread_id thread = options.thread;
|
||||||
|
bool stopInMain = false;
|
||||||
|
|
||||||
|
// If command line arguments were given, start the program.
|
||||||
|
if (options.commandLineArgc > 0) {
|
||||||
|
printf("loading program: \"%s\" ...\n", options.commandLineArgv[0]);
|
||||||
|
// TODO: What about the CWD?
|
||||||
|
thread = load_program(options.commandLineArgv,
|
||||||
|
options.commandLineArgc, false);
|
||||||
|
if (thread < 0) {
|
||||||
|
// TODO: Notify the user!
|
||||||
|
fprintf(stderr, "Error: Failed to load program \"%s\": %s\n",
|
||||||
|
options.commandLineArgv[0], strerror(thread));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
team = thread;
|
||||||
|
// main thread ID == team ID
|
||||||
|
stopInMain = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've got
|
||||||
|
if (team < 0) {
|
||||||
|
printf("no team yet, getting thread info...\n");
|
||||||
|
thread_info threadInfo;
|
||||||
|
status_t error = get_thread_info(thread, &threadInfo);
|
||||||
|
if (error != B_OK) {
|
||||||
|
// TODO: Notify the user!
|
||||||
|
fprintf(stderr, "Error: Failed to get info for thread \"%ld\": "
|
||||||
|
"%s\n", thread, strerror(error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
team = threadInfo.team;
|
||||||
|
}
|
||||||
|
printf("team: %ld, thread: %ld\n", team, thread);
|
||||||
|
|
||||||
|
TeamDebugger* debugger = _FindTeamDebugger(team);
|
||||||
|
if (debugger != NULL) {
|
||||||
|
printf("There's already a debugger for team: %ld\n", team);
|
||||||
|
debugger->Activate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_StartTeamDebugger(team, thread, stopInMain);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TeamDebugger::Listener
|
||||||
|
|
||||||
|
void
|
||||||
|
Debugger::TeamDebuggerStarted(TeamDebugger* debugger)
|
||||||
|
{
|
||||||
|
printf("debugger for team %ld started...\n",
|
||||||
|
debugger->TeamID());
|
||||||
|
|
||||||
|
// Note: see TeamDebuggerQuit() note about locking
|
||||||
|
AutoLocker<Debugger> locker(this);
|
||||||
|
fTeamDebuggers.AddItem(debugger);
|
||||||
|
fRunningTeamDebuggers++;
|
||||||
|
locker.Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Debugger::TeamDebuggerQuit(TeamDebugger* debugger)
|
||||||
|
{
|
||||||
|
// Note: Locking here only works, since we're never locking the other
|
||||||
|
// way around. If we even need to do that, we'll have to introduce a
|
||||||
|
// separate lock to protect the list.
|
||||||
|
|
||||||
|
printf("debugger for team %ld quit.\n",
|
||||||
|
debugger->TeamID());
|
||||||
|
|
||||||
|
AutoLocker<Debugger> locker(this);
|
||||||
|
fTeamDebuggers.RemoveItem(debugger);
|
||||||
|
locker.Unlock();
|
||||||
|
|
||||||
|
if (debugger->Thread() >= 0) {
|
||||||
|
BMessage message(MSG_TEAM_DEBUGGER_QUIT);
|
||||||
|
message.AddInt32("thread", debugger->Thread());
|
||||||
|
PostMessage(&message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Debugger::QuitRequested()
|
||||||
|
{
|
||||||
|
// NOTE: The default implementation will just ask all windows'
|
||||||
|
// QuitRequested() hooks. This in turn will ask the TeamWindows.
|
||||||
|
// For now, this is what we want. If we have more windows later,
|
||||||
|
// like the global TeamsWindow, then we want to just ask the
|
||||||
|
// TeamDebuggers, the TeamsWindow should of course not go away already
|
||||||
|
// if one or more TeamDebuggers want to stay later. There are multiple
|
||||||
|
// ways how to do this. For example, TeamDebugger could get a
|
||||||
|
// QuitRequested() hook or the TeamsWindow and other global windows
|
||||||
|
// could always return false in their QuitRequested().
|
||||||
|
return BApplication::QuitRequested();
|
||||||
|
// TODO: This is ugly. The team debuggers own the windows, not the
|
||||||
|
// other way around.
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Debugger::Quit()
|
||||||
|
{
|
||||||
|
printf("Debugger::Quit(): fRunningTeamDebuggers = %ld, fTeamsWindow = %p\n",
|
||||||
|
fRunningTeamDebuggers, fTeamsWindow);
|
||||||
|
|
||||||
|
// don't quit before all team debuggers have been quit
|
||||||
|
if (fRunningTeamDebuggers <= 0 && fTeamsWindow == NULL)
|
||||||
|
BApplication::Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TeamDebugger*
|
||||||
|
Debugger::_FindTeamDebugger(team_id teamID) const
|
||||||
|
{
|
||||||
|
for (int32 i = 0; TeamDebugger* debugger = fTeamDebuggers.ItemAt(i);
|
||||||
|
i++) {
|
||||||
|
if (debugger->TeamID() == teamID)
|
||||||
|
return debugger;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TeamDebugger*
|
||||||
|
Debugger::_StartTeamDebugger(team_id teamID, thread_id threadID, bool stopInMain)
|
||||||
|
{
|
||||||
|
if (teamID < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
UserInterface* userInterface = new(std::nothrow) GraphicalUserInterface;
|
||||||
|
if (userInterface == NULL) {
|
||||||
|
// TODO: Notify the user!
|
||||||
|
fprintf(stderr, "Error: Out of memory!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Reference<UserInterface> userInterfaceReference(userInterface, true);
|
||||||
|
|
||||||
|
status_t error = B_NO_MEMORY;
|
||||||
|
|
||||||
|
TeamDebugger* debugger = new(std::nothrow) TeamDebugger(this, userInterface,
|
||||||
|
&fSettingsManager);
|
||||||
|
if (debugger)
|
||||||
|
error = debugger->Init(teamID, threadID, stopInMain);
|
||||||
|
|
||||||
|
if (error != B_OK) {
|
||||||
|
printf("Error: debugger for team %ld failed to init: %s!\n",
|
||||||
|
teamID, strerror(error));
|
||||||
|
delete debugger;
|
||||||
|
return NULL;
|
||||||
|
} else
|
||||||
|
printf("debugger for team %ld created and initialized successfully!\n",
|
||||||
|
teamID);
|
||||||
|
|
||||||
|
return debugger;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, const char* const* argv)
|
main(int argc, const char* const* argv)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface ] ;
|
|||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui model ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui model ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui team_window ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui team_window ] ;
|
||||||
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui teams_window ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui util ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui util ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui value ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui value ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) util ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) util ] ;
|
||||||
@@ -164,6 +165,10 @@ Application Debugger :
|
|||||||
VariablesViewState.cpp
|
VariablesViewState.cpp
|
||||||
VariablesViewStateHistory.cpp
|
VariablesViewStateHistory.cpp
|
||||||
|
|
||||||
|
# user_interface/gui/teams_window
|
||||||
|
TeamsWindow.cpp
|
||||||
|
TeamsListView.cpp
|
||||||
|
|
||||||
# user_interface/gui/team_window
|
# user_interface/gui/team_window
|
||||||
BreakpointListView.cpp
|
BreakpointListView.cpp
|
||||||
BreakpointsView.cpp
|
BreakpointsView.cpp
|
||||||
@@ -248,4 +253,3 @@ Application Debugger :
|
|||||||
HaikuSubInclude arch x86 disasm ;
|
HaikuSubInclude arch x86 disasm ;
|
||||||
HaikuSubInclude demangler ;
|
HaikuSubInclude demangler ;
|
||||||
HaikuSubInclude dwarf ;
|
HaikuSubInclude dwarf ;
|
||||||
HaikuSubInclude user_interface gui running_teams_window ;
|
|
||||||
|
|||||||
@@ -41,7 +41,10 @@ enum {
|
|||||||
MSG_VALUE_NODE_CHILDREN_DELETED = 'vncd',
|
MSG_VALUE_NODE_CHILDREN_DELETED = 'vncd',
|
||||||
MSG_VALUE_NODE_VALUE_CHANGED = 'vnvc',
|
MSG_VALUE_NODE_VALUE_CHANGED = 'vnvc',
|
||||||
|
|
||||||
MSG_TEAM_DEBUGGER_QUIT = 'dbqt'
|
MSG_TEAM_DEBUGGER_QUIT = 'dbqt',
|
||||||
|
MSG_SHOW_TEAMS_WINDOW = 'stsw',
|
||||||
|
MSG_TEAMS_WINDOW_CLOSED = 'tswc',
|
||||||
|
MSG_DEBUG_THIS_TEAM = 'dbtt'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
fUserInterface->Show();
|
Activate();
|
||||||
|
|
||||||
// if requested, stop the given thread
|
// if requested, stop the given thread
|
||||||
if (threadID >= 0) {
|
if (threadID >= 0) {
|
||||||
@@ -380,10 +380,19 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fListener->TeamDebuggerStarted(this);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamDebugger::Activate()
|
||||||
|
{
|
||||||
|
fUserInterface->Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TeamDebugger::MessageReceived(BMessage* message)
|
TeamDebugger::MessageReceived(BMessage* message)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ public:
|
|||||||
status_t Init(team_id teamID, thread_id threadID,
|
status_t Init(team_id teamID, thread_id threadID,
|
||||||
bool stopInMain);
|
bool stopInMain);
|
||||||
|
|
||||||
|
void Activate();
|
||||||
|
|
||||||
team_id TeamID() const { return fTeamID; }
|
team_id TeamID() const { return fTeamID; }
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage* message);
|
virtual void MessageReceived(BMessage* message);
|
||||||
@@ -144,6 +146,7 @@ class TeamDebugger::Listener {
|
|||||||
public:
|
public:
|
||||||
virtual ~Listener();
|
virtual ~Listener();
|
||||||
|
|
||||||
|
virtual void TeamDebuggerStarted(TeamDebugger* debugger) = 0;
|
||||||
virtual void TeamDebuggerQuit(TeamDebugger* debugger) = 0;
|
virtual void TeamDebuggerQuit(TeamDebugger* debugger) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
SubDir HAIKU_TOP src apps debugger user_interface gui running_teams_window ;
|
|
||||||
|
|
||||||
CCFLAGS += -Werror ;
|
|
||||||
C++FLAGS += -Werror ;
|
|
||||||
|
|
||||||
UsePrivateHeaders debug ;
|
|
||||||
UsePrivateSystemHeaders ;
|
|
||||||
|
|
||||||
Application hdb :
|
|
||||||
hdb.cpp
|
|
||||||
RunningTeamsWindow.cpp
|
|
||||||
TeamsListView.cpp
|
|
||||||
TeamWindow.cpp
|
|
||||||
|
|
||||||
: be tracker translation libdebug.so $(TARGET_LIBSUPC++)
|
|
||||||
;
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009, Philippe Houdoin, [email protected]. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "hdb.h"
|
|
||||||
|
|
||||||
#include "RunningTeamsWindow.h"
|
|
||||||
#include "TeamsListView.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
#include <Application.h>
|
|
||||||
#include <ListView.h>
|
|
||||||
#include <ScrollView.h>
|
|
||||||
#include <File.h>
|
|
||||||
#include <FindDirectory.h>
|
|
||||||
#include <Path.h>
|
|
||||||
|
|
||||||
RunningTeamsWindow::RunningTeamsWindow()
|
|
||||||
: BWindow(BRect(100, 100, 500, 250), "Running Teams", B_DOCUMENT_WINDOW,
|
|
||||||
B_ASYNCHRONOUS_CONTROLS)
|
|
||||||
{
|
|
||||||
BMessage settings;
|
|
||||||
_LoadSettings(settings);
|
|
||||||
|
|
||||||
BRect frame;
|
|
||||||
if (settings.FindRect("running teams window frame", &frame) == B_OK) {
|
|
||||||
MoveTo(frame.LeftTop());
|
|
||||||
ResizeTo(frame.Width(), frame.Height());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a teams list view
|
|
||||||
frame = Bounds();
|
|
||||||
frame.right -= B_V_SCROLL_BAR_WIDTH;
|
|
||||||
|
|
||||||
fTeamsListView = new TeamsListView(frame, "RunningTeamsList");
|
|
||||||
fTeamsListView->SetInvocationMessage(new BMessage(kMsgDebugThisTeam));
|
|
||||||
|
|
||||||
BScrollView * teamsScroller = new BScrollView("RunningTeamsListScroller",
|
|
||||||
fTeamsListView, B_FOLLOW_ALL_SIDES, 0, false, true, B_NO_BORDER);
|
|
||||||
|
|
||||||
AddChild(teamsScroller);
|
|
||||||
|
|
||||||
// small visual tweak
|
|
||||||
if (BScrollBar* scrollBar = teamsScroller->ScrollBar(B_VERTICAL)) {
|
|
||||||
scrollBar->MoveBy(0, -1);
|
|
||||||
scrollBar->ResizeBy(0, -(B_H_SCROLL_BAR_HEIGHT - 2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RunningTeamsWindow::~RunningTeamsWindow()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
RunningTeamsWindow::MessageReceived(BMessage* message)
|
|
||||||
{
|
|
||||||
switch (message->what) {
|
|
||||||
case kMsgDebugThisTeam:
|
|
||||||
{
|
|
||||||
TeamListItem* item = dynamic_cast<TeamListItem*>(fTeamsListView->ItemAt(
|
|
||||||
fTeamsListView->CurrentSelection()));
|
|
||||||
|
|
||||||
if (item != NULL) {
|
|
||||||
BMessage message(kMsgOpenTeamWindow);
|
|
||||||
message.AddInt32("team_id", item->TeamID());
|
|
||||||
be_app_messenger.SendMessage(&message);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
BWindow::MessageReceived(message);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
RunningTeamsWindow::QuitRequested()
|
|
||||||
{
|
|
||||||
_SaveSettings();
|
|
||||||
|
|
||||||
be_app_messenger.SendMessage(kMsgRunningTeamsWindowClosed);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark --
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
RunningTeamsWindow::_OpenSettings(BFile& file, uint32 mode)
|
|
||||||
{
|
|
||||||
BPath path;
|
|
||||||
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
path.Append("Debugger settings");
|
|
||||||
|
|
||||||
return file.SetTo(path.Path(), mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
RunningTeamsWindow::_LoadSettings(BMessage& settings)
|
|
||||||
{
|
|
||||||
BFile file;
|
|
||||||
status_t status = _OpenSettings(file, B_READ_ONLY);
|
|
||||||
if (status < B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
return settings.Unflatten(&file);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
RunningTeamsWindow::_SaveSettings()
|
|
||||||
{
|
|
||||||
BFile file;
|
|
||||||
status_t status = _OpenSettings(file,
|
|
||||||
B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
|
|
||||||
|
|
||||||
if (status < B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
BMessage settings('hdbg');
|
|
||||||
status = settings.AddRect("running teams window frame", Frame());
|
|
||||||
if (status != B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
if (status == B_OK)
|
|
||||||
status = settings.Flatten(&file);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009, Philippe Houdoin, [email protected]. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef RUNNING_TEAMS_WINDOW_H
|
|
||||||
#define RUNNING_TEAMS_WINDOW_H
|
|
||||||
|
|
||||||
#include <Window.h>
|
|
||||||
|
|
||||||
class BListView;
|
|
||||||
class BFile;
|
|
||||||
class BMessage;
|
|
||||||
|
|
||||||
|
|
||||||
class RunningTeamsWindow : public BWindow {
|
|
||||||
public:
|
|
||||||
RunningTeamsWindow();
|
|
||||||
virtual ~RunningTeamsWindow();
|
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage* message);
|
|
||||||
virtual bool QuitRequested();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
status_t _OpenSettings(BFile& file, uint32 mode);
|
|
||||||
status_t _LoadSettings(BMessage& settings);
|
|
||||||
status_t _SaveSettings();
|
|
||||||
|
|
||||||
BListView* fTeamsListView;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32 kMsgDebugThisTeam = 'dbtm';
|
|
||||||
|
|
||||||
#endif // RUNNING_TEAMS_WINDOW_H
|
|
||||||
@@ -1,373 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2008, Philippe Houdoin, [email protected]. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "hdb.h"
|
|
||||||
#include "TeamWindow.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
#include <String.h>
|
|
||||||
#include <Application.h>
|
|
||||||
#include <File.h>
|
|
||||||
#include <FindDirectory.h>
|
|
||||||
#include <Path.h>
|
|
||||||
#include <debugger.h>
|
|
||||||
|
|
||||||
|
|
||||||
TeamWindow::TeamWindow(team_id team)
|
|
||||||
: BWindow(BRect(100, 100, 500, 250), "Running Teams", B_DOCUMENT_WINDOW,
|
|
||||||
B_ASYNCHRONOUS_CONTROLS),
|
|
||||||
fTeam(team),
|
|
||||||
fNubThread(-1),
|
|
||||||
fNubPort(-1),
|
|
||||||
fListenerThread(-1),
|
|
||||||
fListenerPort(-1)
|
|
||||||
{
|
|
||||||
BMessage settings;
|
|
||||||
_LoadSettings(settings);
|
|
||||||
|
|
||||||
BRect frame;
|
|
||||||
if (settings.FindRect("team window frame", &frame) == B_OK) {
|
|
||||||
MoveTo(frame.LeftTop());
|
|
||||||
ResizeTo(frame.Width(), frame.Height());
|
|
||||||
}
|
|
||||||
|
|
||||||
team_info info;
|
|
||||||
get_team_info(team, &info);
|
|
||||||
|
|
||||||
BString title;
|
|
||||||
title << "Team " << fTeam << ": " << info.args;
|
|
||||||
|
|
||||||
SetTitle(title.String());
|
|
||||||
|
|
||||||
_InstallDebugger();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TeamWindow::~TeamWindow()
|
|
||||||
{
|
|
||||||
_RemoveDebugger();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TeamWindow::MessageReceived(BMessage* message)
|
|
||||||
{
|
|
||||||
switch (message->what) {
|
|
||||||
default:
|
|
||||||
BWindow::MessageReceived(message);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
TeamWindow::QuitRequested()
|
|
||||||
{
|
|
||||||
/* _SaveSettings();
|
|
||||||
|
|
||||||
BMessage update(kMsgSettingsChanged);
|
|
||||||
update.AddRect("window_frame", Frame());
|
|
||||||
be_app_messenger.SendMessage(&update);
|
|
||||||
*/
|
|
||||||
be_app_messenger.SendMessage(kMsgWindowClosed);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark --
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
TeamWindow::_InstallDebugger()
|
|
||||||
{
|
|
||||||
char name[32];
|
|
||||||
status_t result;
|
|
||||||
|
|
||||||
snprintf(name, sizeof(name), "team %ld nub listener", fTeam);
|
|
||||||
printf("Starting %s...\n", name);
|
|
||||||
|
|
||||||
// create listener port
|
|
||||||
fListenerPort = create_port(10, name);
|
|
||||||
if (fListenerPort < 0)
|
|
||||||
return fListenerPort;
|
|
||||||
|
|
||||||
// spawn the listener thread
|
|
||||||
fListenerThread = spawn_thread(_ListenerEntry, name,
|
|
||||||
B_NORMAL_PRIORITY, this);
|
|
||||||
if (fListenerThread < 0)
|
|
||||||
return fListenerThread;
|
|
||||||
|
|
||||||
// register as this team debugger
|
|
||||||
printf("Installing team %ld debugger on port 0x%lx...\n",
|
|
||||||
fTeam, fListenerPort);
|
|
||||||
fNubPort = install_team_debugger(fTeam, fListenerPort);
|
|
||||||
if (fNubPort < 0)
|
|
||||||
return fNubPort;
|
|
||||||
|
|
||||||
// init the debug context
|
|
||||||
result = init_debug_context(&fDebugContext, fTeam, fNubPort);
|
|
||||||
if (result != B_OK) {
|
|
||||||
fprintf(stderr, "Failed to init debug context for team %ld: %s\n",
|
|
||||||
fTeam, strerror(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
// get team nub thread
|
|
||||||
team_info teamInfo;
|
|
||||||
result = get_team_info(fTeam, &teamInfo);
|
|
||||||
if (result != B_OK) {
|
|
||||||
fprintf(stderr, "Failed to get info for team %ld: %s\n",
|
|
||||||
fTeam, strerror(result));
|
|
||||||
}
|
|
||||||
fNubThread = teamInfo.debugger_nub_thread;
|
|
||||||
|
|
||||||
// set the team debug flags
|
|
||||||
debug_nub_set_team_flags message;
|
|
||||||
message.flags =
|
|
||||||
B_TEAM_DEBUG_SIGNALS |
|
|
||||||
// B_TEAM_DEBUG_PRE_SYSCALL |
|
|
||||||
// B_TEAM_DEBUG_POST_SYSCALL |
|
|
||||||
B_TEAM_DEBUG_TEAM_CREATION |
|
|
||||||
B_TEAM_DEBUG_THREADS |
|
|
||||||
B_TEAM_DEBUG_IMAGES |
|
|
||||||
// B_TEAM_DEBUG_STOP_NEW_THREADS |
|
|
||||||
0;
|
|
||||||
|
|
||||||
send_debug_message(&fDebugContext,
|
|
||||||
B_DEBUG_MESSAGE_SET_TEAM_FLAGS, &message, sizeof(message), NULL, 0);
|
|
||||||
|
|
||||||
// resume the listener
|
|
||||||
resume_thread(fListenerThread);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
TeamWindow::_RemoveDebugger()
|
|
||||||
{
|
|
||||||
if (fListenerPort < 0)
|
|
||||||
// No debugger installed (yet?)
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
printf("Stopping team %ld nub listener...\n", fTeam);
|
|
||||||
|
|
||||||
printf("Removing team %ld debugger installed on port 0x%lx...\n",
|
|
||||||
fTeam, fListenerPort);
|
|
||||||
status_t status = remove_team_debugger(fTeam);
|
|
||||||
|
|
||||||
delete_port(fListenerPort);
|
|
||||||
if (fListenerThread >= 0 && find_thread(NULL) != fListenerThread) {
|
|
||||||
status_t result;
|
|
||||||
wait_for_thread(fListenerThread, &result);
|
|
||||||
fListenerThread = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
destroy_debug_context(&fDebugContext);
|
|
||||||
fListenerPort = -1;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
TeamWindow::_ListenerEntry(void *data)
|
|
||||||
{
|
|
||||||
return ((TeamWindow*) data)->_Listener();
|
|
||||||
}
|
|
||||||
|
|
||||||
// _Listener
|
|
||||||
status_t
|
|
||||||
TeamWindow::_Listener()
|
|
||||||
{
|
|
||||||
printf("Team %ld nub listener on port 0x%lx started...\n", fTeam, fListenerPort);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
// receive the next debug message
|
|
||||||
debug_debugger_message code;
|
|
||||||
debug_debugger_message_data data;
|
|
||||||
ssize_t bytesRead;
|
|
||||||
|
|
||||||
do {
|
|
||||||
bytesRead = read_port(fListenerPort, (int32 *) &code, &data,
|
|
||||||
sizeof(debug_debugger_message_data));
|
|
||||||
} while (bytesRead == B_INTERRUPTED);
|
|
||||||
|
|
||||||
if (bytesRead == B_BAD_PORT_ID)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (bytesRead < 0) {
|
|
||||||
fprintf(stderr, "Team %ld nub listener: failed to read from "
|
|
||||||
"listener port: %s. Terminating!\n",
|
|
||||||
fTeam, strerror(bytesRead));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
_HandleDebugMessage(code, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Team %ld nub listener on port 0x%lx stopped.\n", fTeam, fListenerPort);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
TeamWindow::_HandleDebugMessage(debug_debugger_message code,
|
|
||||||
debug_debugger_message_data & data)
|
|
||||||
{
|
|
||||||
char dump[512];
|
|
||||||
get_debug_message_string(code, dump, sizeof(dump));
|
|
||||||
|
|
||||||
printf("Team %ld nub listener: code %d from team %ld received: %s\n",
|
|
||||||
fTeam, code, data.origin.team, dump);
|
|
||||||
|
|
||||||
switch (code) {
|
|
||||||
case B_DEBUGGER_MESSAGE_DEBUGGER_CALL:
|
|
||||||
{
|
|
||||||
// print the debugger message
|
|
||||||
char debuggerMessage[1024];
|
|
||||||
ssize_t bytesRead = debug_read_string(&fDebugContext,
|
|
||||||
data.debugger_call.message, debuggerMessage,
|
|
||||||
sizeof(debuggerMessage));
|
|
||||||
if (bytesRead > 0) {
|
|
||||||
printf(" Thread %ld called debugger(): %s\n",
|
|
||||||
data.origin.thread, debuggerMessage);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, " Thread %ld called debugger(), but failed"
|
|
||||||
"to get the debugger message.\n",
|
|
||||||
data.origin.thread);
|
|
||||||
}
|
|
||||||
// fall through...
|
|
||||||
}
|
|
||||||
case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED:
|
|
||||||
case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT:
|
|
||||||
case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT:
|
|
||||||
case B_DEBUGGER_MESSAGE_SINGLE_STEP: {
|
|
||||||
// ATM, just continue
|
|
||||||
debug_nub_continue_thread message;
|
|
||||||
message.thread = data.origin.thread;
|
|
||||||
message.handle_event = B_THREAD_DEBUG_HANDLE_EVENT;
|
|
||||||
message.single_step = false; // run full speed
|
|
||||||
|
|
||||||
status_t result= send_debug_message(&fDebugContext,
|
|
||||||
B_DEBUG_MESSAGE_CONTINUE_THREAD, &message, sizeof(message),
|
|
||||||
NULL, 0);
|
|
||||||
if (result != B_OK) {
|
|
||||||
fprintf(stderr, "Failed to resume thread %ld: %s\n",
|
|
||||||
message.thread, strerror(result));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case B_DEBUGGER_MESSAGE_PRE_SYSCALL:
|
|
||||||
printf(" pre_syscall.syscall = %ld\n", data.pre_syscall.syscall);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_DEBUGGER_MESSAGE_POST_SYSCALL:
|
|
||||||
printf(" post_syscall.syscall = %ld\n", data.post_syscall.syscall);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED:
|
|
||||||
printf(" signal_received.signal = %d\n",
|
|
||||||
data.signal_received.signal);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED:
|
|
||||||
{
|
|
||||||
// print the exception message
|
|
||||||
char exception[1024];
|
|
||||||
get_debug_exception_string(data.exception_occurred.exception,
|
|
||||||
exception, sizeof(exception));
|
|
||||||
printf(" Thread %ld caused an exception: signal %d, %s\n",
|
|
||||||
data.origin.thread, data.exception_occurred.signal, exception);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case B_DEBUGGER_MESSAGE_TEAM_CREATED:
|
|
||||||
case B_DEBUGGER_MESSAGE_TEAM_DELETED:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_DEBUGGER_MESSAGE_THREAD_CREATED:
|
|
||||||
printf(" thread_created.new_thread = %ld\n",
|
|
||||||
data.thread_created.new_thread);
|
|
||||||
break;
|
|
||||||
case B_DEBUGGER_MESSAGE_THREAD_DELETED:
|
|
||||||
printf(" thread_deleted.origin.thread = %ld\n",
|
|
||||||
data.thread_deleted.origin.thread);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_DEBUGGER_MESSAGE_IMAGE_CREATED:
|
|
||||||
printf(" id = %ld, type = %d, name = %s\n",
|
|
||||||
data.image_created.info.id,
|
|
||||||
data.image_created.info.type,
|
|
||||||
data.image_created.info.name);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_DEBUGGER_MESSAGE_IMAGE_DELETED:
|
|
||||||
printf(" id = %ld, type = %d, name = %s\n",
|
|
||||||
data.image_deleted.info.id,
|
|
||||||
data.image_deleted.info.type,
|
|
||||||
data.image_deleted.info.name);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// unknown message, ignore
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----
|
|
||||||
|
|
||||||
status_t
|
|
||||||
TeamWindow::_OpenSettings(BFile& file, uint32 mode)
|
|
||||||
{
|
|
||||||
BPath path;
|
|
||||||
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
path.Append("Debugger settings");
|
|
||||||
|
|
||||||
return file.SetTo(path.Path(), mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
TeamWindow::_LoadSettings(BMessage& settings)
|
|
||||||
{
|
|
||||||
BFile file;
|
|
||||||
status_t status = _OpenSettings(file, B_READ_ONLY);
|
|
||||||
if (status < B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
return settings.Unflatten(&file);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
TeamWindow::_SaveSettings()
|
|
||||||
{
|
|
||||||
BFile file;
|
|
||||||
status_t status = _OpenSettings(file,
|
|
||||||
B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
|
|
||||||
|
|
||||||
if (status < B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
BMessage settings('hdbg');
|
|
||||||
status = settings.AddRect("team window frame", Frame());
|
|
||||||
if (status != B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
if (status == B_OK)
|
|
||||||
status = settings.Flatten(&file);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2008, Philippe Houdoin, [email protected]. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TEAM_WINDOW_H
|
|
||||||
#define TEAM_WINDOW_H
|
|
||||||
|
|
||||||
#include <Window.h>
|
|
||||||
#include <debug_support.h>
|
|
||||||
|
|
||||||
class BFile;
|
|
||||||
class BMessage;
|
|
||||||
|
|
||||||
|
|
||||||
class TeamWindow : public BWindow {
|
|
||||||
public:
|
|
||||||
TeamWindow(team_id team);
|
|
||||||
virtual ~TeamWindow();
|
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage* message);
|
|
||||||
virtual bool QuitRequested();
|
|
||||||
|
|
||||||
team_id Team() { return fTeam; };
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
status_t _InstallDebugger();
|
|
||||||
status_t _RemoveDebugger();
|
|
||||||
|
|
||||||
static status_t _ListenerEntry(void *data);
|
|
||||||
status_t _Listener();
|
|
||||||
status_t _HandleDebugMessage(debug_debugger_message message,
|
|
||||||
debug_debugger_message_data & data);
|
|
||||||
|
|
||||||
status_t _OpenSettings(BFile& file, uint32 mode);
|
|
||||||
status_t _LoadSettings(BMessage& settings);
|
|
||||||
status_t _SaveSettings();
|
|
||||||
|
|
||||||
// ----
|
|
||||||
|
|
||||||
team_id fTeam;
|
|
||||||
thread_id fNubThread;
|
|
||||||
port_id fNubPort;
|
|
||||||
debug_context fDebugContext;
|
|
||||||
|
|
||||||
thread_id fListenerThread;
|
|
||||||
port_id fListenerPort;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // TEAM_WINDOW_H
|
|
||||||
@@ -1,343 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009, Philippe Houdoin, [email protected]. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "TeamsListView.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <ListView.h>
|
|
||||||
#include <Bitmap.h>
|
|
||||||
#include <FindDirectory.h>
|
|
||||||
#include <NodeInfo.h>
|
|
||||||
#include <Path.h>
|
|
||||||
#include <Roster.h>
|
|
||||||
#include <MimeType.h>
|
|
||||||
#include <MessageRunner.h>
|
|
||||||
#include <String.h>
|
|
||||||
|
|
||||||
|
|
||||||
TeamListItem::TeamListItem(team_info & info)
|
|
||||||
: BStringItem("", false),
|
|
||||||
fIcon(NULL)
|
|
||||||
{
|
|
||||||
_SetTo(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TeamListItem::TeamListItem(team_id team)
|
|
||||||
: BStringItem("", false),
|
|
||||||
fIcon(NULL)
|
|
||||||
{
|
|
||||||
team_info info;
|
|
||||||
get_team_info(team, &info);
|
|
||||||
_SetTo(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TeamListItem::~TeamListItem()
|
|
||||||
{
|
|
||||||
delete fIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TeamListItem::DrawItem(BView *owner, BRect frame, bool complete)
|
|
||||||
{
|
|
||||||
BRect rect = frame;
|
|
||||||
|
|
||||||
if (fIcon) {
|
|
||||||
rgb_color highColor = owner->HighColor();
|
|
||||||
rgb_color lowColor = owner->LowColor();
|
|
||||||
|
|
||||||
if (IsSelected() || complete) {
|
|
||||||
// Draw the background...
|
|
||||||
if (IsSelected())
|
|
||||||
owner->SetLowColor(tint_color(lowColor, B_DARKEN_2_TINT));
|
|
||||||
|
|
||||||
owner->FillRect(rect, B_SOLID_LOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
BPoint point(rect.left + 2.0f,
|
|
||||||
rect.top + (rect.Height() - B_MINI_ICON) / 2.0f);
|
|
||||||
|
|
||||||
// Draw icon
|
|
||||||
owner->SetDrawingMode(B_OP_ALPHA);
|
|
||||||
owner->DrawBitmap(fIcon, point);
|
|
||||||
owner->SetDrawingMode(B_OP_COPY);
|
|
||||||
|
|
||||||
owner->MovePenTo(rect.left + B_MINI_ICON + 8.0f, frame.top + fBaselineOffset);
|
|
||||||
|
|
||||||
if (!IsEnabled())
|
|
||||||
owner->SetHighColor(tint_color(owner->HighColor(), B_LIGHTEN_2_TINT));
|
|
||||||
else
|
|
||||||
owner->SetHighColor(0, 0, 0);
|
|
||||||
|
|
||||||
owner->DrawString(Text());
|
|
||||||
|
|
||||||
owner->SetHighColor(highColor);
|
|
||||||
owner->SetLowColor(lowColor);
|
|
||||||
} else
|
|
||||||
// No icon, fallback on plain StringItem...
|
|
||||||
BStringItem::DrawItem(owner, rect, complete);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TeamListItem::Update(BView *owner, const BFont *font)
|
|
||||||
{
|
|
||||||
BStringItem::Update(owner, font);
|
|
||||||
|
|
||||||
if (Height() < B_MINI_ICON + 4.0f)
|
|
||||||
SetHeight(B_MINI_ICON + 4.0f);
|
|
||||||
|
|
||||||
font_height fontHeight;
|
|
||||||
font->GetHeight(&fontHeight);
|
|
||||||
|
|
||||||
fBaselineOffset = fontHeight.ascent +
|
|
||||||
+ (Height() - ceilf(fontHeight.ascent + fontHeight.descent)) / 2.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* static */
|
|
||||||
int
|
|
||||||
TeamListItem::Compare(const void* a, const void* b)
|
|
||||||
{
|
|
||||||
const BListItem *itemA = *static_cast<const BListItem * const *>(a);
|
|
||||||
const BListItem *itemB = *static_cast<const BListItem * const *>(b);
|
|
||||||
const TeamListItem *teamItemA = dynamic_cast<const TeamListItem *>(itemA);
|
|
||||||
const TeamListItem *teamItemB = dynamic_cast<const TeamListItem *>(itemB);
|
|
||||||
|
|
||||||
if (teamItemA != NULL && teamItemB != NULL) {
|
|
||||||
return teamItemA->fTeamInfo.team - teamItemB->fTeamInfo.team;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
TeamListItem::_SetTo(team_info & info)
|
|
||||||
{
|
|
||||||
BPath systemPath;
|
|
||||||
team_info teamInfo = fTeamInfo = info;
|
|
||||||
|
|
||||||
find_directory(B_BEOS_SYSTEM_DIRECTORY, &systemPath);
|
|
||||||
|
|
||||||
// strip any trailing space(s)...
|
|
||||||
for (int len = strlen(teamInfo.args) - 1;
|
|
||||||
len >= 0 && teamInfo.args[len] == ' '; len--) {
|
|
||||||
teamInfo.args[len] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
app_info appInfo;
|
|
||||||
status_t status = be_roster->GetRunningAppInfo(teamInfo.team, &appInfo);
|
|
||||||
|
|
||||||
if (status == B_OK || teamInfo.team == B_SYSTEM_TEAM) {
|
|
||||||
if (teamInfo.team == B_SYSTEM_TEAM) {
|
|
||||||
// Get icon and name from kernel
|
|
||||||
system_info systemInfo;
|
|
||||||
get_system_info(&systemInfo);
|
|
||||||
|
|
||||||
BPath kernelPath(systemPath);
|
|
||||||
kernelPath.Append(systemInfo.kernel_name);
|
|
||||||
|
|
||||||
get_ref_for_path(kernelPath.Path(), &appInfo.ref);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
BEntry entry(teamInfo.args, true);
|
|
||||||
entry.GetRef(&appInfo.ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetText(teamInfo.args);
|
|
||||||
|
|
||||||
fIcon = new BBitmap(BRect(0, 0, B_MINI_ICON - 1, B_MINI_ICON - 1), B_RGBA32);
|
|
||||||
|
|
||||||
status = BNodeInfo::GetTrackerIcon(&appInfo.ref, fIcon, B_MINI_ICON);
|
|
||||||
if (status != B_OK) {
|
|
||||||
BMimeType genericAppType(B_APP_MIME_TYPE);
|
|
||||||
status = genericAppType.GetIcon(fIcon, B_MINI_ICON);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status != B_OK) {
|
|
||||||
delete fIcon;
|
|
||||||
fIcon = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
TeamsListView::TeamsListView(BRect frame, const char* name)
|
|
||||||
: BListView(frame, name, B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL),
|
|
||||||
fUpdateRunner(NULL)
|
|
||||||
{
|
|
||||||
team_info tmi;
|
|
||||||
get_team_info(B_CURRENT_TEAM, &tmi);
|
|
||||||
fThisTeam = tmi.team;
|
|
||||||
|
|
||||||
#ifdef __HAIKU__
|
|
||||||
SetFlags(Flags() | B_SUBPIXEL_PRECISE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TeamsListView::~TeamsListView()
|
|
||||||
{
|
|
||||||
delete fUpdateRunner;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TeamsListView::AttachedToWindow()
|
|
||||||
{
|
|
||||||
BListView::AttachedToWindow();
|
|
||||||
|
|
||||||
_InitList();
|
|
||||||
|
|
||||||
be_roster->StartWatching(this, B_REQUEST_LAUNCHED | B_REQUEST_QUIT);
|
|
||||||
|
|
||||||
BMessage msg(kMsgUpdateTeamsList);
|
|
||||||
fUpdateRunner = new BMessageRunner(this, &msg, 100000L); // 10Hz
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TeamsListView::DetachedFromWindow()
|
|
||||||
{
|
|
||||||
BListView::DetachedFromWindow();
|
|
||||||
|
|
||||||
be_roster->StopWatching(this);
|
|
||||||
|
|
||||||
delete fUpdateRunner;
|
|
||||||
fUpdateRunner = NULL;
|
|
||||||
|
|
||||||
// free all items, they will be retrieved again in AttachedToWindow()
|
|
||||||
for (int32 i = CountItems(); i-- > 0;) {
|
|
||||||
delete ItemAt(i);
|
|
||||||
}
|
|
||||||
MakeEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TeamsListView::MessageReceived(BMessage* message)
|
|
||||||
{
|
|
||||||
switch (message->what) {
|
|
||||||
case kMsgUpdateTeamsList:
|
|
||||||
_UpdateList();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_SOME_APP_LAUNCHED:
|
|
||||||
{
|
|
||||||
team_id team;
|
|
||||||
if (message->FindInt32("be:team", &team) != B_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
AddItem(new TeamListItem(team));
|
|
||||||
SortItems(&TeamListItem::Compare);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case B_SOME_APP_QUIT:
|
|
||||||
{
|
|
||||||
team_id team;
|
|
||||||
if (message->FindInt32("be:team", &team) != B_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
TeamListItem *item = FindItem(team);
|
|
||||||
if (item != NULL) {
|
|
||||||
RemoveItem(item);
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
BListView::MessageReceived(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TeamListItem *
|
|
||||||
TeamsListView::FindItem(team_id teamId)
|
|
||||||
{
|
|
||||||
for (int32 i = CountItems(); i-- > 0;) {
|
|
||||||
TeamListItem* item = dynamic_cast<TeamListItem*>(ItemAt(i));
|
|
||||||
if (item == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (item->TeamID() == teamId)
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TeamsListView::_InitList()
|
|
||||||
{
|
|
||||||
int32 tmi_cookie = 0;
|
|
||||||
team_info tmi;
|
|
||||||
|
|
||||||
while (get_next_team_info(&tmi_cookie, &tmi) == B_OK) {
|
|
||||||
TeamListItem * item = new TeamListItem(tmi);
|
|
||||||
|
|
||||||
if (tmi.team == B_SYSTEM_TEAM ||
|
|
||||||
tmi.team == fThisTeam)
|
|
||||||
// We don't support debugging kernel and... ourself!
|
|
||||||
// Don't show these two teams
|
|
||||||
continue;
|
|
||||||
|
|
||||||
AddItem(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SortItems(&TeamListItem::Compare);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TeamsListView::_UpdateList()
|
|
||||||
{
|
|
||||||
int32 tmi_cookie = 0;
|
|
||||||
team_info tmi;
|
|
||||||
TeamListItem *item;
|
|
||||||
int32 index = 0;
|
|
||||||
|
|
||||||
// NOTA: assuming get_next_team_info() returns team ordered by team ID...
|
|
||||||
while (get_next_team_info(&tmi_cookie, &tmi) == B_OK) {
|
|
||||||
|
|
||||||
if (tmi.team == B_SYSTEM_TEAM ||
|
|
||||||
tmi.team == fThisTeam)
|
|
||||||
continue; // Ignore kernel and ourself teams
|
|
||||||
|
|
||||||
item = (TeamListItem *) ItemAt(index);
|
|
||||||
|
|
||||||
while (item && tmi.team > item->TeamID()) {
|
|
||||||
RemoveItem(item);
|
|
||||||
delete item;
|
|
||||||
item = (TeamListItem *) ItemAt(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!item || tmi.team != item->TeamID()) {
|
|
||||||
// Team not found in known teams list: insert an new item
|
|
||||||
TeamListItem * item = new TeamListItem(tmi);
|
|
||||||
if (!item)
|
|
||||||
index++; // No item with team id bigger found: insert at list end
|
|
||||||
|
|
||||||
AddItem(item, index);
|
|
||||||
}
|
|
||||||
index++; // Move list sync head.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove tail list items, if we don't walk list thru the end
|
|
||||||
while ((item = (TeamListItem *) ItemAt(index)) != NULL) {
|
|
||||||
RemoveItem(item);
|
|
||||||
delete item;
|
|
||||||
item = (TeamListItem *) ItemAt(++index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009, Philippe Houdoin, [email protected]. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TEAMS_LIST_ITEM_H
|
|
||||||
#define TEAMS_LIST_ITEM_H
|
|
||||||
|
|
||||||
#include <ListView.h>
|
|
||||||
#include <StringItem.h>
|
|
||||||
#include <OS.h>
|
|
||||||
|
|
||||||
class BBitmap;
|
|
||||||
class BMessageRunner;
|
|
||||||
|
|
||||||
|
|
||||||
class TeamListItem : public BStringItem {
|
|
||||||
public:
|
|
||||||
TeamListItem(team_info & teamInfo);
|
|
||||||
TeamListItem(team_id teamId);
|
|
||||||
|
|
||||||
virtual ~TeamListItem();
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual void DrawItem(BView *owner, BRect itemRect,
|
|
||||||
bool drawEverything = false);
|
|
||||||
virtual void Update(BView *owner, const BFont *font);
|
|
||||||
|
|
||||||
team_id TeamID() { return fTeamInfo.team; };
|
|
||||||
|
|
||||||
static int Compare(const void* a, const void* b);
|
|
||||||
|
|
||||||
private:
|
|
||||||
status_t _SetTo(team_info & info);
|
|
||||||
|
|
||||||
team_info fTeamInfo;
|
|
||||||
BBitmap * fIcon;
|
|
||||||
float fBaselineOffset;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class TeamsListView : public BListView {
|
|
||||||
public:
|
|
||||||
TeamsListView(BRect frame, const char* name);
|
|
||||||
virtual ~TeamsListView();
|
|
||||||
|
|
||||||
TeamListItem* FindItem(team_id teamId);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void AttachedToWindow();
|
|
||||||
virtual void DetachedFromWindow();
|
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage* message);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void _InitList();
|
|
||||||
void _UpdateList();
|
|
||||||
|
|
||||||
BMessageRunner* fUpdateRunner;
|
|
||||||
team_id fThisTeam;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32 kMsgUpdateTeamsList = 'uptl';
|
|
||||||
|
|
||||||
#endif // TEAMS_LIST_VIEW_H
|
|
||||||
@@ -1,247 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009, Philippe Houdoin, [email protected]. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "hdb.h"
|
|
||||||
|
|
||||||
#include "RunningTeamsWindow.h"
|
|
||||||
#include "TeamWindow.h"
|
|
||||||
|
|
||||||
#include <Application.h>
|
|
||||||
#include <Alert.h>
|
|
||||||
#include <TextView.h>
|
|
||||||
#include <FindDirectory.h>
|
|
||||||
#include <Directory.h>
|
|
||||||
#include <Entry.h>
|
|
||||||
#include <Path.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
const char* kSignature = "application/x-vnd.Haiku-Debugger";
|
|
||||||
|
|
||||||
class Debugger : public BApplication {
|
|
||||||
public:
|
|
||||||
Debugger();
|
|
||||||
virtual ~Debugger();
|
|
||||||
|
|
||||||
virtual void ReadyToRun();
|
|
||||||
|
|
||||||
virtual void RefsReceived(BMessage *message);
|
|
||||||
virtual void ArgvReceived(int32 argc, char **argv);
|
|
||||||
virtual void MessageReceived(BMessage *message);
|
|
||||||
|
|
||||||
virtual void AboutRequested();
|
|
||||||
|
|
||||||
static void ShowAbout();
|
|
||||||
|
|
||||||
private:
|
|
||||||
status_t Debug(team_id team);
|
|
||||||
status_t Debug(BEntry &entry);
|
|
||||||
|
|
||||||
RunningTeamsWindow * fRunningTeamsWindow;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Debugger::Debugger()
|
|
||||||
: BApplication(kSignature),
|
|
||||||
fRunningTeamsWindow(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Debugger::~Debugger()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Debugger::Debug(BEntry &entry)
|
|
||||||
{
|
|
||||||
// Does the file really exist?
|
|
||||||
if (!entry.Exists())
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
BWindow *window = new TeamWindow(0); // team);
|
|
||||||
window->Show();
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Debugger::Debug(team_id team)
|
|
||||||
{
|
|
||||||
// int32 teamWindows = 0;
|
|
||||||
|
|
||||||
// Do we already have that window open?
|
|
||||||
for (int32 i = CountWindows(); i-- > 0; ) {
|
|
||||||
TeamWindow *window = dynamic_cast<TeamWindow *>(WindowAt(i));
|
|
||||||
if (window == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (window->Team() == team) {
|
|
||||||
window->Activate(true);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
// teamWindows++;
|
|
||||||
}
|
|
||||||
|
|
||||||
BWindow *window = new TeamWindow(team);
|
|
||||||
window->Show();
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Debugger::ReadyToRun()
|
|
||||||
{
|
|
||||||
// are there already windows open?
|
|
||||||
if (CountWindows() != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// if not, open the running teams window
|
|
||||||
PostMessage(kMsgOpenRunningTeamsWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Debugger::RefsReceived(BMessage *message)
|
|
||||||
{
|
|
||||||
int32 index = 0;
|
|
||||||
entry_ref ref;
|
|
||||||
while (message->FindRef("refs", index++, &ref) == B_OK) {
|
|
||||||
BEntry entry;
|
|
||||||
status_t status = entry.SetTo(&ref);
|
|
||||||
|
|
||||||
if (status == B_OK)
|
|
||||||
status = Debug(entry);
|
|
||||||
|
|
||||||
if (status != B_OK) {
|
|
||||||
char buffer[1024];
|
|
||||||
snprintf(buffer, sizeof(buffer),
|
|
||||||
"Could not debug \"%s\":\n"
|
|
||||||
"%s",
|
|
||||||
ref.name, strerror(status));
|
|
||||||
|
|
||||||
(new BAlert("Debugger request",
|
|
||||||
buffer, "OK", NULL, NULL,
|
|
||||||
B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Debugger::ArgvReceived(int32 argc, char **argv)
|
|
||||||
{
|
|
||||||
BMessage *message = CurrentMessage();
|
|
||||||
|
|
||||||
BDirectory currentDirectory;
|
|
||||||
if (message)
|
|
||||||
currentDirectory.SetTo(message->FindString("cwd"));
|
|
||||||
|
|
||||||
BMessage refs;
|
|
||||||
|
|
||||||
for (int i = 1 ; i < argc ; i++) {
|
|
||||||
BPath path;
|
|
||||||
if (argv[i][0] == '/')
|
|
||||||
path.SetTo(argv[i]);
|
|
||||||
else
|
|
||||||
path.SetTo(¤tDirectory, argv[i]);
|
|
||||||
|
|
||||||
status_t status;
|
|
||||||
entry_ref ref;
|
|
||||||
BEntry entry;
|
|
||||||
|
|
||||||
if ((status = entry.SetTo(path.Path(), false)) != B_OK
|
|
||||||
|| (status = entry.GetRef(&ref)) != B_OK) {
|
|
||||||
fprintf(stderr, "Could not open file \"%s\": %s\n", path.Path(), strerror(status));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
refs.AddRef("refs", &ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
RefsReceived(&refs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Debugger::MessageReceived(BMessage *message)
|
|
||||||
{
|
|
||||||
switch (message->what) {
|
|
||||||
case kMsgOpenRunningTeamsWindow:
|
|
||||||
if (fRunningTeamsWindow == NULL) {
|
|
||||||
fRunningTeamsWindow = new RunningTeamsWindow();
|
|
||||||
fRunningTeamsWindow->Show();
|
|
||||||
} else
|
|
||||||
fRunningTeamsWindow->Activate(true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case kMsgRunningTeamsWindowClosed:
|
|
||||||
fRunningTeamsWindow = NULL;
|
|
||||||
// supposed to fall through
|
|
||||||
case kMsgWindowClosed:
|
|
||||||
if (CountWindows() == 1)
|
|
||||||
// Last window is being closed: quit application
|
|
||||||
PostMessage(B_QUIT_REQUESTED);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case kMsgOpenTeamWindow:
|
|
||||||
{
|
|
||||||
team_id team;
|
|
||||||
if (message->FindInt32("team_id", &team) == B_OK)
|
|
||||||
Debug(team);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
BApplication::MessageReceived(message);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Debugger::AboutRequested()
|
|
||||||
{
|
|
||||||
ShowAbout();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*static*/ void
|
|
||||||
Debugger::ShowAbout()
|
|
||||||
{
|
|
||||||
BAlert *alert = new BAlert("about", "Debugger\n"
|
|
||||||
"\twritten by Philippe Houdoin\n"
|
|
||||||
"\tCopyright 2009, Haiku, Inc.\n", "OK");
|
|
||||||
BTextView *view = alert->TextView();
|
|
||||||
BFont font;
|
|
||||||
|
|
||||||
view->SetStylable(true);
|
|
||||||
|
|
||||||
view->GetFont(&font);
|
|
||||||
font.SetSize(18);
|
|
||||||
font.SetFace(B_BOLD_FACE);
|
|
||||||
view->SetFontAndColor(0, 15, &font);
|
|
||||||
|
|
||||||
alert->Go();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int /* argc */, char ** /* argv */)
|
|
||||||
{
|
|
||||||
Debugger app;
|
|
||||||
app.Run();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009, Philippe Houdoin, [email protected]. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HDB_H
|
|
||||||
#define HDB_H
|
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
|
||||||
|
|
||||||
static const uint32 kMsgOpenRunningTeamsWindow = 'OpRt';
|
|
||||||
static const uint32 kMsgRunningTeamsWindowClosed = 'ClRt';
|
|
||||||
static const uint32 kMsgWindowClosed = 'WiCl';
|
|
||||||
|
|
||||||
static const uint32 kMsgOpenTeamWindow = 'OpTw';
|
|
||||||
|
|
||||||
#endif /* HDB_H */
|
|
||||||
@@ -0,0 +1,340 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009-2010, Philippe Houdoin, [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <ListView.h>
|
||||||
|
#include <Bitmap.h>
|
||||||
|
#include <FindDirectory.h>
|
||||||
|
#include <NodeInfo.h>
|
||||||
|
#include <Path.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
#include <MimeType.h>
|
||||||
|
#include <MessageRunner.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include "TeamsListView.h"
|
||||||
|
|
||||||
|
|
||||||
|
TeamListItem::TeamListItem(team_info & info)
|
||||||
|
: BStringItem("", false),
|
||||||
|
fIcon(NULL)
|
||||||
|
{
|
||||||
|
_SetTo(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TeamListItem::TeamListItem(team_id team)
|
||||||
|
: BStringItem("", false),
|
||||||
|
fIcon(NULL)
|
||||||
|
{
|
||||||
|
team_info info;
|
||||||
|
get_team_info(team, &info);
|
||||||
|
_SetTo(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TeamListItem::~TeamListItem()
|
||||||
|
{
|
||||||
|
delete fIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamListItem::DrawItem(BView *owner, BRect frame, bool complete)
|
||||||
|
{
|
||||||
|
BRect rect = frame;
|
||||||
|
|
||||||
|
if (fIcon) {
|
||||||
|
rgb_color highColor = owner->HighColor();
|
||||||
|
rgb_color lowColor = owner->LowColor();
|
||||||
|
|
||||||
|
if (IsSelected() || complete) {
|
||||||
|
// Draw the background...
|
||||||
|
if (IsSelected())
|
||||||
|
owner->SetLowColor(tint_color(lowColor, B_DARKEN_2_TINT));
|
||||||
|
|
||||||
|
owner->FillRect(rect, B_SOLID_LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
BPoint point(rect.left + 2.0f,
|
||||||
|
rect.top + (rect.Height() - B_MINI_ICON) / 2.0f);
|
||||||
|
|
||||||
|
// Draw icon
|
||||||
|
owner->SetDrawingMode(B_OP_ALPHA);
|
||||||
|
owner->DrawBitmap(fIcon, point);
|
||||||
|
owner->SetDrawingMode(B_OP_COPY);
|
||||||
|
|
||||||
|
owner->MovePenTo(rect.left + B_MINI_ICON + 8.0f, frame.top + fBaselineOffset);
|
||||||
|
|
||||||
|
if (!IsEnabled())
|
||||||
|
owner->SetHighColor(tint_color(owner->HighColor(), B_LIGHTEN_2_TINT));
|
||||||
|
else
|
||||||
|
owner->SetHighColor(0, 0, 0);
|
||||||
|
|
||||||
|
owner->DrawString(Text());
|
||||||
|
|
||||||
|
owner->SetHighColor(highColor);
|
||||||
|
owner->SetLowColor(lowColor);
|
||||||
|
} else
|
||||||
|
// No icon, fallback on plain StringItem...
|
||||||
|
BStringItem::DrawItem(owner, rect, complete);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamListItem::Update(BView *owner, const BFont *font)
|
||||||
|
{
|
||||||
|
BStringItem::Update(owner, font);
|
||||||
|
|
||||||
|
if (Height() < B_MINI_ICON + 4.0f)
|
||||||
|
SetHeight(B_MINI_ICON + 4.0f);
|
||||||
|
|
||||||
|
font_height fontHeight;
|
||||||
|
font->GetHeight(&fontHeight);
|
||||||
|
|
||||||
|
fBaselineOffset = fontHeight.ascent +
|
||||||
|
+ (Height() - ceilf(fontHeight.ascent + fontHeight.descent)) / 2.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
int
|
||||||
|
TeamListItem::Compare(const void* a, const void* b)
|
||||||
|
{
|
||||||
|
const BListItem *itemA = *static_cast<const BListItem * const *>(a);
|
||||||
|
const BListItem *itemB = *static_cast<const BListItem * const *>(b);
|
||||||
|
const TeamListItem *teamItemA = dynamic_cast<const TeamListItem *>(itemA);
|
||||||
|
const TeamListItem *teamItemB = dynamic_cast<const TeamListItem *>(itemB);
|
||||||
|
|
||||||
|
if (teamItemA != NULL && teamItemB != NULL) {
|
||||||
|
return teamItemA->fTeamInfo.team - teamItemB->fTeamInfo.team;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
TeamListItem::_SetTo(team_info & info)
|
||||||
|
{
|
||||||
|
BPath systemPath;
|
||||||
|
team_info teamInfo = fTeamInfo = info;
|
||||||
|
|
||||||
|
find_directory(B_BEOS_SYSTEM_DIRECTORY, &systemPath);
|
||||||
|
|
||||||
|
// strip any trailing space(s)...
|
||||||
|
for (int len = strlen(teamInfo.args) - 1;
|
||||||
|
len >= 0 && teamInfo.args[len] == ' '; len--) {
|
||||||
|
teamInfo.args[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
app_info appInfo;
|
||||||
|
status_t status = be_roster->GetRunningAppInfo(teamInfo.team, &appInfo);
|
||||||
|
|
||||||
|
if (status == B_OK || teamInfo.team == B_SYSTEM_TEAM) {
|
||||||
|
if (teamInfo.team == B_SYSTEM_TEAM) {
|
||||||
|
// Get icon and name from kernel
|
||||||
|
system_info systemInfo;
|
||||||
|
get_system_info(&systemInfo);
|
||||||
|
|
||||||
|
BPath kernelPath(systemPath);
|
||||||
|
kernelPath.Append(systemInfo.kernel_name);
|
||||||
|
|
||||||
|
get_ref_for_path(kernelPath.Path(), &appInfo.ref);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
BEntry entry(teamInfo.args, true);
|
||||||
|
entry.GetRef(&appInfo.ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetText(teamInfo.args);
|
||||||
|
|
||||||
|
fIcon = new BBitmap(BRect(0, 0, B_MINI_ICON - 1, B_MINI_ICON - 1), B_RGBA32);
|
||||||
|
|
||||||
|
status = BNodeInfo::GetTrackerIcon(&appInfo.ref, fIcon, B_MINI_ICON);
|
||||||
|
if (status != B_OK) {
|
||||||
|
BMimeType genericAppType(B_APP_MIME_TYPE);
|
||||||
|
status = genericAppType.GetIcon(fIcon, B_MINI_ICON);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != B_OK) {
|
||||||
|
delete fIcon;
|
||||||
|
fIcon = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
TeamsListView::TeamsListView(BRect frame, const char* name)
|
||||||
|
: BListView(frame, name, B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL),
|
||||||
|
fUpdateRunner(NULL)
|
||||||
|
{
|
||||||
|
team_info tmi;
|
||||||
|
get_team_info(B_CURRENT_TEAM, &tmi);
|
||||||
|
fThisTeam = tmi.team;
|
||||||
|
|
||||||
|
#ifdef __HAIKU__
|
||||||
|
SetFlags(Flags() | B_SUBPIXEL_PRECISE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TeamsListView::~TeamsListView()
|
||||||
|
{
|
||||||
|
delete fUpdateRunner;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamsListView::AttachedToWindow()
|
||||||
|
{
|
||||||
|
BListView::AttachedToWindow();
|
||||||
|
|
||||||
|
_InitList();
|
||||||
|
|
||||||
|
be_roster->StartWatching(this, B_REQUEST_LAUNCHED | B_REQUEST_QUIT);
|
||||||
|
|
||||||
|
BMessage msg(kMsgUpdateTeamsList);
|
||||||
|
fUpdateRunner = new BMessageRunner(this, &msg, 100000L); // 10Hz
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamsListView::DetachedFromWindow()
|
||||||
|
{
|
||||||
|
BListView::DetachedFromWindow();
|
||||||
|
|
||||||
|
be_roster->StopWatching(this);
|
||||||
|
|
||||||
|
delete fUpdateRunner;
|
||||||
|
fUpdateRunner = NULL;
|
||||||
|
|
||||||
|
// free all items, they will be retrieved again in AttachedToWindow()
|
||||||
|
for (int32 i = CountItems(); i-- > 0;) {
|
||||||
|
delete ItemAt(i);
|
||||||
|
}
|
||||||
|
MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamsListView::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case kMsgUpdateTeamsList:
|
||||||
|
_UpdateList();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_SOME_APP_LAUNCHED:
|
||||||
|
{
|
||||||
|
team_id team;
|
||||||
|
if (message->FindInt32("be:team", &team) != B_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
AddItem(new TeamListItem(team));
|
||||||
|
SortItems(&TeamListItem::Compare);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_SOME_APP_QUIT:
|
||||||
|
{
|
||||||
|
team_id team;
|
||||||
|
if (message->FindInt32("be:team", &team) != B_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
TeamListItem *item = FindItem(team);
|
||||||
|
if (item != NULL) {
|
||||||
|
RemoveItem(item);
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
BListView::MessageReceived(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TeamListItem *
|
||||||
|
TeamsListView::FindItem(team_id teamId)
|
||||||
|
{
|
||||||
|
for (int32 i = CountItems(); i-- > 0;) {
|
||||||
|
TeamListItem* item = dynamic_cast<TeamListItem*>(ItemAt(i));
|
||||||
|
if (item == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (item->TeamID() == teamId)
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamsListView::_InitList()
|
||||||
|
{
|
||||||
|
int32 tmi_cookie = 0;
|
||||||
|
team_info tmi;
|
||||||
|
|
||||||
|
while (get_next_team_info(&tmi_cookie, &tmi) == B_OK) {
|
||||||
|
TeamListItem * item = new TeamListItem(tmi);
|
||||||
|
|
||||||
|
if (tmi.team == B_SYSTEM_TEAM ||
|
||||||
|
tmi.team == fThisTeam) {
|
||||||
|
// We don't support debugging kernel and... ourself!
|
||||||
|
item->SetEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SortItems(&TeamListItem::Compare);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamsListView::_UpdateList()
|
||||||
|
{
|
||||||
|
int32 tmi_cookie = 0;
|
||||||
|
team_info tmi;
|
||||||
|
TeamListItem *item;
|
||||||
|
int32 index = 0;
|
||||||
|
|
||||||
|
// NOTA: assuming get_next_team_info() returns team ordered by team ID...
|
||||||
|
while (get_next_team_info(&tmi_cookie, &tmi) == B_OK) {
|
||||||
|
|
||||||
|
item = (TeamListItem *) ItemAt(index);
|
||||||
|
while (item && tmi.team > item->TeamID()) {
|
||||||
|
RemoveItem(item);
|
||||||
|
delete item;
|
||||||
|
item = (TeamListItem *) ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!item || tmi.team != item->TeamID()) {
|
||||||
|
// Team not found in known teams list: insert an new item
|
||||||
|
TeamListItem * item = new TeamListItem(tmi);
|
||||||
|
if (!item)
|
||||||
|
index++; // No item with team id bigger found: insert at list end
|
||||||
|
|
||||||
|
AddItem(item, index);
|
||||||
|
}
|
||||||
|
index++; // Move list sync head.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove tail list items, if we don't walk list thru the end
|
||||||
|
while ((item = (TeamListItem *) ItemAt(index)) != NULL) {
|
||||||
|
RemoveItem(item);
|
||||||
|
delete item;
|
||||||
|
item = (TeamListItem *) ItemAt(++index);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009-2010, Philippe Houdoin, [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef TEAMS_LIST_ITEM_H
|
||||||
|
#define TEAMS_LIST_ITEM_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <ListView.h>
|
||||||
|
#include <StringItem.h>
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
class BBitmap;
|
||||||
|
class BMessageRunner;
|
||||||
|
|
||||||
|
|
||||||
|
class TeamListItem : public BStringItem {
|
||||||
|
public:
|
||||||
|
TeamListItem(team_info & teamInfo);
|
||||||
|
TeamListItem(team_id teamId);
|
||||||
|
|
||||||
|
virtual ~TeamListItem();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void DrawItem(BView *owner, BRect itemRect,
|
||||||
|
bool drawEverything = false);
|
||||||
|
virtual void Update(BView *owner, const BFont *font);
|
||||||
|
|
||||||
|
team_id TeamID() { return fTeamInfo.team; };
|
||||||
|
|
||||||
|
static int Compare(const void* a, const void* b);
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _SetTo(team_info & info);
|
||||||
|
|
||||||
|
private:
|
||||||
|
team_info fTeamInfo;
|
||||||
|
BBitmap * fIcon;
|
||||||
|
float fBaselineOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class TeamsListView : public BListView {
|
||||||
|
public:
|
||||||
|
TeamsListView(BRect frame, const char* name);
|
||||||
|
virtual ~TeamsListView();
|
||||||
|
|
||||||
|
TeamListItem* FindItem(team_id teamId);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void AttachedToWindow();
|
||||||
|
virtual void DetachedFromWindow();
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InitList();
|
||||||
|
void _UpdateList();
|
||||||
|
|
||||||
|
private:
|
||||||
|
BMessageRunner* fUpdateRunner;
|
||||||
|
team_id fThisTeam;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint32 kMsgUpdateTeamsList = 'uptl';
|
||||||
|
|
||||||
|
#endif // TEAMS_LIST_VIEW_H
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009-2010, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include <Application.h>
|
||||||
|
#include <ListView.h>
|
||||||
|
#include <ScrollView.h>
|
||||||
|
#include <File.h>
|
||||||
|
#include <FindDirectory.h>
|
||||||
|
#include <Path.h>
|
||||||
|
|
||||||
|
#include "MessageCodes.h"
|
||||||
|
#include "TeamsWindow.h"
|
||||||
|
#include "TeamsListView.h"
|
||||||
|
|
||||||
|
|
||||||
|
TeamsWindow::TeamsWindow()
|
||||||
|
: BWindow(BRect(100, 100, 500, 250), "Teams", B_DOCUMENT_WINDOW,
|
||||||
|
B_ASYNCHRONOUS_CONTROLS)
|
||||||
|
{
|
||||||
|
BMessage settings;
|
||||||
|
_LoadSettings(settings);
|
||||||
|
|
||||||
|
BRect frame;
|
||||||
|
if (settings.FindRect("teams window frame", &frame) == B_OK) {
|
||||||
|
MoveTo(frame.LeftTop());
|
||||||
|
ResizeTo(frame.Width(), frame.Height());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add button to start a team debugger
|
||||||
|
// TODO: add UI to setup arguments and environ, launch a program
|
||||||
|
// and start his team debugger
|
||||||
|
|
||||||
|
// Add a teams list view
|
||||||
|
frame = Bounds();
|
||||||
|
frame.right -= B_V_SCROLL_BAR_WIDTH;
|
||||||
|
|
||||||
|
fTeamsListView = new TeamsListView(frame, "TeamsList");
|
||||||
|
fTeamsListView->SetInvocationMessage(new BMessage(kMsgDebugThisTeam));
|
||||||
|
|
||||||
|
BScrollView * teamsScroller = new BScrollView("TeamsListScroller",
|
||||||
|
fTeamsListView, B_FOLLOW_ALL_SIDES, 0, false, true, B_NO_BORDER);
|
||||||
|
|
||||||
|
AddChild(teamsScroller);
|
||||||
|
|
||||||
|
// small visual tweak
|
||||||
|
if (BScrollBar* scrollBar = teamsScroller->ScrollBar(B_VERTICAL)) {
|
||||||
|
scrollBar->MoveBy(0, -1);
|
||||||
|
scrollBar->ResizeBy(0, -(B_H_SCROLL_BAR_HEIGHT - 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TeamsWindow::~TeamsWindow()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamsWindow::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case kMsgDebugThisTeam:
|
||||||
|
{
|
||||||
|
TeamListItem* item = dynamic_cast<TeamListItem*>(fTeamsListView->ItemAt(
|
||||||
|
fTeamsListView->CurrentSelection()));
|
||||||
|
|
||||||
|
if (item != NULL) {
|
||||||
|
BMessage message(MSG_DEBUG_THIS_TEAM);
|
||||||
|
message.AddInt32("team", item->TeamID());
|
||||||
|
be_app_messenger.SendMessage(&message);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
BWindow::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
TeamsWindow::QuitRequested()
|
||||||
|
{
|
||||||
|
_SaveSettings();
|
||||||
|
|
||||||
|
be_app_messenger.SendMessage(MSG_TEAMS_WINDOW_CLOSED);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark --
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
TeamsWindow::_OpenSettings(BFile& file, uint32 mode)
|
||||||
|
{
|
||||||
|
BPath path;
|
||||||
|
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
path.Append("Debugger settings");
|
||||||
|
|
||||||
|
return file.SetTo(path.Path(), mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
TeamsWindow::_LoadSettings(BMessage& settings)
|
||||||
|
{
|
||||||
|
BFile file;
|
||||||
|
status_t status = _OpenSettings(file, B_READ_ONLY);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return settings.Unflatten(&file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
TeamsWindow::_SaveSettings()
|
||||||
|
{
|
||||||
|
BFile file;
|
||||||
|
status_t status = _OpenSettings(file,
|
||||||
|
B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
|
||||||
|
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
BMessage settings('hdbg');
|
||||||
|
status = settings.AddRect("teams window frame", Frame());
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (status == B_OK)
|
||||||
|
status = settings.Flatten(&file);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009-2010, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef TEAMS_WINDOW_H
|
||||||
|
#define TEAMS_WINDOW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Window.h>
|
||||||
|
|
||||||
|
class BListView;
|
||||||
|
class BFile;
|
||||||
|
class BMessage;
|
||||||
|
|
||||||
|
|
||||||
|
class TeamsWindow : public BWindow {
|
||||||
|
public:
|
||||||
|
TeamsWindow();
|
||||||
|
virtual ~TeamsWindow();
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
virtual bool QuitRequested();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
status_t _OpenSettings(BFile& file, uint32 mode);
|
||||||
|
status_t _LoadSettings(BMessage& settings);
|
||||||
|
status_t _SaveSettings();
|
||||||
|
|
||||||
|
private:
|
||||||
|
BListView* fTeamsListView;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint32 kMsgDebugThisTeam = 'dbtm';
|
||||||
|
|
||||||
|
#endif // TEAMS_WINDOW_H
|
||||||
Reference in New Issue
Block a user