diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index dc286e2f37..94295a10ce 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -21,3 +21,5 @@ Application Debugger : : $(TARGET_LIBSUPC++) ; + +HaikuSubInclude gui running_teams_window ; diff --git a/src/apps/debugger/gui/running_teams_window/Jamfile b/src/apps/debugger/gui/running_teams_window/Jamfile new file mode 100644 index 0000000000..6f265c3548 --- /dev/null +++ b/src/apps/debugger/gui/running_teams_window/Jamfile @@ -0,0 +1,16 @@ +SubDir HAIKU_TOP src apps debugger 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 +; diff --git a/src/apps/debugger/gui/running_teams_window/RunningTeamsWindow.cpp b/src/apps/debugger/gui/running_teams_window/RunningTeamsWindow.cpp new file mode 100644 index 0000000000..c148146beb --- /dev/null +++ b/src/apps/debugger/gui/running_teams_window/RunningTeamsWindow.cpp @@ -0,0 +1,138 @@ +/* + * Copyright 2009, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "hdb.h" + +#include "RunningTeamsWindow.h" +#include "TeamsListView.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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 + BRect rect = Bounds(); + rect.right -= B_V_SCROLL_BAR_WIDTH; + fTeamsListView = new TeamsListView(rect, "RunningTeamsList", B_FOLLOW_ALL); + + // Set the message sent on team list item invocation + fTeamsListView->SetInvocationMessage(new BMessage(kMsgDebugThisTeam)); + + BScrollView * scroller = new BScrollView("RunningTeamsListScroller", + fTeamsListView, B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FRAME_EVENTS, + false, true); // Vertical scrollbar only + + AddChild(scroller); +} + + +RunningTeamsWindow::~RunningTeamsWindow() +{ +} + + +void +RunningTeamsWindow::MessageReceived(BMessage* message) +{ + switch (message->what) { + case kMsgDebugThisTeam: + { + TeamListItem* item = dynamic_cast(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; +} diff --git a/src/apps/debugger/gui/running_teams_window/RunningTeamsWindow.h b/src/apps/debugger/gui/running_teams_window/RunningTeamsWindow.h new file mode 100644 index 0000000000..658648afcd --- /dev/null +++ b/src/apps/debugger/gui/running_teams_window/RunningTeamsWindow.h @@ -0,0 +1,36 @@ +/* + * Copyright 2009, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef RUNNING_TEAMS_WINDOW_H +#define RUNNING_TEAMS_WINDOW_H + +#include + +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 diff --git a/src/apps/debugger/gui/running_teams_window/TeamWindow.cpp b/src/apps/debugger/gui/running_teams_window/TeamWindow.cpp new file mode 100644 index 0000000000..3e81d2bd2a --- /dev/null +++ b/src/apps/debugger/gui/running_teams_window/TeamWindow.cpp @@ -0,0 +1,373 @@ +/* + * Copyright 2008, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "hdb.h" +#include "TeamWindow.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +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; +} diff --git a/src/apps/debugger/gui/running_teams_window/TeamWindow.h b/src/apps/debugger/gui/running_teams_window/TeamWindow.h new file mode 100644 index 0000000000..58d49a47ae --- /dev/null +++ b/src/apps/debugger/gui/running_teams_window/TeamWindow.h @@ -0,0 +1,51 @@ +/* + * Copyright 2008, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef TEAM_WINDOW_H +#define TEAM_WINDOW_H + +#include +#include + +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 diff --git a/src/apps/debugger/gui/running_teams_window/TeamsListView.cpp b/src/apps/debugger/gui/running_teams_window/TeamsListView.cpp new file mode 100644 index 0000000000..2eb196f21c --- /dev/null +++ b/src/apps/debugger/gui/running_teams_window/TeamsListView.cpp @@ -0,0 +1,339 @@ +/* + * Copyright 2009, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "TeamsListView.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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(a); + const BListItem *itemB = *static_cast(b); + const TeamListItem *teamItemA = dynamic_cast(itemA); + const TeamListItem *teamItemB = dynamic_cast(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 rect, const char* name, uint32 resizingMode) + : BListView(rect, name, B_SINGLE_SELECTION_LIST, resizingMode), + fUpdateRunner(NULL) +{ + team_info tmi; + get_team_info(B_CURRENT_TEAM, &tmi); + fThisTeam = tmi.team; +} + + +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(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); + } +} diff --git a/src/apps/debugger/gui/running_teams_window/TeamsListView.h b/src/apps/debugger/gui/running_teams_window/TeamsListView.h new file mode 100644 index 0000000000..13249a2db4 --- /dev/null +++ b/src/apps/debugger/gui/running_teams_window/TeamsListView.h @@ -0,0 +1,66 @@ +/* + * Copyright 2009, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef TEAMS_LIST_ITEM_H +#define TEAMS_LIST_ITEM_H + +#include +#include +#include + +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 rect, const char* name, + uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP); + 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 diff --git a/src/apps/debugger/gui/running_teams_window/hdb.cpp b/src/apps/debugger/gui/running_teams_window/hdb.cpp new file mode 100644 index 0000000000..84c1aa4918 --- /dev/null +++ b/src/apps/debugger/gui/running_teams_window/hdb.cpp @@ -0,0 +1,247 @@ +/* + * Copyright 2009, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "hdb.h" + +#include "RunningTeamsWindow.h" +#include "TeamWindow.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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(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; +} diff --git a/src/apps/debugger/gui/running_teams_window/hdb.h b/src/apps/debugger/gui/running_teams_window/hdb.h new file mode 100644 index 0000000000..a6bd3a0c46 --- /dev/null +++ b/src/apps/debugger/gui/running_teams_window/hdb.h @@ -0,0 +1,17 @@ +/* + * Copyright 2009, Philippe Houdoin, phoudoin@haiku-os.org. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef HDB_H +#define HDB_H + +#include + +static const uint32 kMsgOpenRunningTeamsWindow = 'OpRt'; +static const uint32 kMsgRunningTeamsWindowClosed = 'ClRt'; +static const uint32 kMsgWindowClosed = 'WiCl'; + +static const uint32 kMsgOpenTeamWindow = 'OpTw'; + +#endif /* HDB_H */