void TeamWindow::_SetActiveThread(::Thread* thread) { if (thread == fActiveThread) return; if (fActiveThread != NULL) fActiveThread->ReleaseReference(); fActiveThread = thread; if (fActiveThread != NULL) fActiveThread->AcquireReference(); AutoLocker< ::Team> locker(fTeam); _UpdateRunButtons(); StackTrace* stackTrace = fActiveThread != NULL ? fActiveThread->GetStackTrace() : NULL; BReference<StackTrace> stackTraceReference(stackTrace); // hold a reference until we've set it locker.Unlock(); fThreadListView->SetThread(fActiveThread); _SetActiveStackTrace(stackTrace); _UpdateCpuState(); }
void TeamWindow::_HandleThreadStateChanged(thread_id threadID) { AutoLocker< ::Team> locker(fTeam); ::Thread* thread = fTeam->ThreadByID(threadID); if (thread == NULL) return; // If the thread has been stopped and we don't have an active thread yet // (or it isn't stopped), switch to this thread. Otherwise ignore the event. if (thread->State() == THREAD_STATE_STOPPED && (fActiveThread == NULL || (thread != fActiveThread && fActiveThread->State() != THREAD_STATE_STOPPED))) { _SetActiveThread(thread); } else if (thread != fActiveThread) { // otherwise ignore the event, if the thread is not the active one return; } // Switch to the threads tab view when the thread has stopped. if (thread->State() == THREAD_STATE_STOPPED) { fTabView->Select(MAIN_TAB_INDEX_THREADS); // if we hit a breakpoint or exception, raise the window to the // foreground, since if this occurs while e.g. debugging a GUI // app, it might not be immediately obvious that such an event // occurred as the app may simply appear to hang. Activate(); } _UpdateRunButtons(); }
void TeamWindow::_HandleThreadStateChanged(thread_id threadID) { AutoLocker< ::Team> locker(fTeam); ::Thread* thread = fTeam->ThreadByID(threadID); if (thread == NULL) return; // If the thread has been stopped and we don't have an active thread yet // (or it isn't stopped), switch to this thread. Otherwise ignore the event. if (thread->State() == THREAD_STATE_STOPPED && (fActiveThread == NULL || (thread != fActiveThread && fActiveThread->State() != THREAD_STATE_STOPPED))) { _SetActiveThread(thread); } else if (thread != fActiveThread) { // otherwise ignore the event, if the thread is not the active one return; } // Switch to the threads tab view when the thread has stopped. if (thread->State() == THREAD_STATE_STOPPED) fTabView->Select(MAIN_TAB_INDEX_THREADS); _UpdateRunButtons(); }
void TeamWindow::_Init() { BScrollView* sourceScrollView; const float splitSpacing = 3.0f; BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f) .Add(fMenuBar = new BMenuBar("Menu")) .AddSplit(B_VERTICAL, splitSpacing) .GetSplitView(&fFunctionSplitView) .SetInsets(B_USE_SMALL_INSETS) .Add(fTabView = new BTabView("tab view"), 0.4f) .AddSplit(B_HORIZONTAL, splitSpacing) .GetSplitView(&fSourceSplitView) .AddGroup(B_VERTICAL, B_USE_SMALL_SPACING) .AddGroup(B_HORIZONTAL, B_USE_SMALL_SPACING) .Add(fRunButton = new BButton("Run")) .Add(fStepOverButton = new BButton("Step over")) .Add(fStepIntoButton = new BButton("Step into")) .Add(fStepOutButton = new BButton("Step out")) .AddGlue() .End() .Add(fSourcePathView = new BStringView( "source path", "Source path unavailable."), 4.0f) .Add(sourceScrollView = new BScrollView("source scroll", NULL, 0, true, true), splitSpacing) .End() .Add(fLocalsTabView = new BTabView("locals view")) .End() .AddSplit(B_VERTICAL, splitSpacing) .GetSplitView(&fConsoleSplitView) .SetInsets(0.0) .Add(fConsoleOutputView = ConsoleOutputView::Create()) .End() .End(); // add source view sourceScrollView->SetTarget(fSourceView = SourceView::Create(fTeam, this)); // add threads tab BSplitView* threadGroup = new BSplitView(B_HORIZONTAL, splitSpacing); threadGroup->SetName("Threads"); fTabView->AddTab(threadGroup); BLayoutBuilder::Split<>(threadGroup) .GetSplitView(&fThreadSplitView) .Add(fThreadListView = ThreadListView::Create(fTeam, this)) .Add(fStackTraceView = StackTraceView::Create(this)); // add images tab BSplitView* imagesGroup = new BSplitView(B_HORIZONTAL, splitSpacing); imagesGroup->SetName("Images"); fTabView->AddTab(imagesGroup); BLayoutBuilder::Split<>(imagesGroup) .GetSplitView(&fImageSplitView) .Add(fImageListView = ImageListView::Create(fTeam, this)) .Add(fImageFunctionsView = ImageFunctionsView::Create(this)); // add breakpoints tab BGroupView* breakpointsGroup = new BGroupView(B_HORIZONTAL, B_USE_SMALL_SPACING); breakpointsGroup->SetName("Breakpoints"); fTabView->AddTab(breakpointsGroup); BLayoutBuilder::Group<>(breakpointsGroup) // .SetInsets(0.0f) .Add(fBreakpointsView = BreakpointsView::Create(fTeam, this)); // add local variables tab BView* tab = fVariablesView = VariablesView::Create(this); fLocalsTabView->AddTab(tab); // add registers tab tab = fRegistersView = RegistersView::Create(fTeam->GetArchitecture()); fLocalsTabView->AddTab(tab); fRunButton->SetMessage(new BMessage(MSG_THREAD_RUN)); fStepOverButton->SetMessage(new BMessage(MSG_THREAD_STEP_OVER)); fStepIntoButton->SetMessage(new BMessage(MSG_THREAD_STEP_INTO)); fStepOutButton->SetMessage(new BMessage(MSG_THREAD_STEP_OUT)); fRunButton->SetTarget(this); fStepOverButton->SetTarget(this); fStepIntoButton->SetTarget(this); fStepOutButton->SetTarget(this); fSourcePathView->SetExplicitMinSize(BSize(100.0, B_SIZE_UNSET)); fSourcePathView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); BMessageFilter* filter = new(std::nothrow) PathViewMessageFilter( BMessenger(this)); if (filter != NULL) fSourcePathView->AddFilter(filter); // add menus and menu items BMenu* menu = new BMenu("Team"); fMenuBar->AddItem(menu); BMenuItem* item = new BMenuItem("Restart", new BMessage( MSG_TEAM_RESTART_REQUESTED), 'R', B_SHIFT_KEY); menu->AddItem(item); item->SetTarget(this); item = new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 'W'); menu->AddItem(item); item->SetTarget(this); menu = new BMenu("Edit"); fMenuBar->AddItem(menu); item = new BMenuItem("Copy", new BMessage(B_COPY), 'C'); menu->AddItem(item); item->SetTarget(this); item = new BMenuItem("Select all", new BMessage(B_SELECT_ALL), 'A'); menu->AddItem(item); item->SetTarget(this); menu = new BMenu("Tools"); fMenuBar->AddItem(menu); item = new BMenuItem("Save debug report", new BMessage(MSG_CHOOSE_DEBUG_REPORT_LOCATION)); menu->AddItem(item); item->SetTarget(this); item = new BMenuItem("Inspect memory", new BMessage(MSG_SHOW_INSPECTOR_WINDOW), 'I'); menu->AddItem(item); item->SetTarget(this); AutoLocker< ::Team> locker(fTeam); _UpdateRunButtons(); }
void TeamWindow::MessageReceived(BMessage* message) { switch (message->what) { case MSG_TEAM_RESTART_REQUESTED: { fListener->TeamRestartRequested(); break; } case MSG_CHOOSE_DEBUG_REPORT_LOCATION: { try { char filename[B_FILE_NAME_LENGTH]; UiUtils::ReportNameForTeam(fTeam, filename, sizeof(filename)); BMessenger msgr(this); fFilePanel = new BFilePanel(B_SAVE_PANEL, &msgr, NULL, 0, false, new BMessage(MSG_GENERATE_DEBUG_REPORT)); fFilePanel->SetSaveText(filename); fFilePanel->Show(); } catch (...) { delete fFilePanel; fFilePanel = NULL; } break; } case MSG_GENERATE_DEBUG_REPORT: { delete fFilePanel; fFilePanel = NULL; BPath path; entry_ref ref; if (message->FindRef("directory", &ref) == B_OK && message->HasString("name")) { path.SetTo(&ref); path.Append(message->FindString("name")); if (get_ref_for_path(path.Path(), &ref) == B_OK) fListener->DebugReportRequested(&ref); } break; } case MSG_DEBUG_REPORT_SAVED: { BString data; data.SetToFormat("Debug report successfully saved to '%s'", message->FindString("path")); BAlert *alert = new(std::nothrow) BAlert("Report saved", data.String(), "Close"); if (alert == NULL) break; alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); alert->Go(); break; } case MSG_SHOW_INSPECTOR_WINDOW: { if (fInspectorWindow) { fInspectorWindow->Activate(true); } else { try { fInspectorWindow = InspectorWindow::Create(fTeam, fListener, this); if (fInspectorWindow != NULL) { BMessage settings; fInspectorWindow->LoadSettings(fUiSettings); fInspectorWindow->Show(); } } catch (...) { // TODO: notify user } } target_addr_t address; if (message->FindUInt64("address", &address) == B_OK) { BMessage addressMessage(MSG_INSPECT_ADDRESS); addressMessage.AddUInt64("address", address); fInspectorWindow->PostMessage(&addressMessage); } break; } case MSG_INSPECTOR_WINDOW_CLOSED: { _SaveInspectorSettings(CurrentMessage()); fInspectorWindow = NULL; break; } case MSG_SHOW_BREAK_CONDITION_CONFIG_WINDOW: { if (fBreakConditionConfigWindow) { fBreakConditionConfigWindow->Activate(true); } else { try { fBreakConditionConfigWindow = BreakConditionConfigWindow::Create( fTeam, fListener, this); if (fBreakConditionConfigWindow != NULL) fBreakConditionConfigWindow->Show(); } catch (...) { // TODO: notify user } } break; } case MSG_BREAK_CONDITION_CONFIG_WINDOW_CLOSED: { fBreakConditionConfigWindow = NULL; break; } case MSG_SHOW_WATCH_VARIABLE_PROMPT: { target_addr_t address; uint32 type; int32 length; if (message->FindUInt64("address", &address) != B_OK || message->FindUInt32("type", &type) != B_OK || message->FindInt32("length", &length) != B_OK) { break; } try { WatchPromptWindow* window = WatchPromptWindow::Create( fTeam->GetArchitecture(), address, type, length, fListener); window->Show(); } catch (...) { // TODO: notify user } break; } case B_REFS_RECEIVED: { entry_ref locatedPath; if (message->FindRef("refs", &locatedPath) != B_OK) break; _HandleResolveMissingSourceFile(locatedPath); break; } case MSG_LOCATE_SOURCE_IF_NEEDED: { if (fActiveFunction != NULL && fActiveFunction->GetFunctionDebugInfo() ->SourceFile() != NULL && fActiveSourceCode != NULL && fActiveSourceCode->GetSourceFile() == NULL && fActiveFunction->GetFunction()->SourceCodeState() != FUNCTION_SOURCE_NOT_LOADED) { try { if (fFilePanel == NULL) { fFilePanel = new BFilePanel(B_OPEN_PANEL, new BMessenger(this)); } fFilePanel->Show(); } catch (...) { delete fFilePanel; fFilePanel = NULL; } } break; } case MSG_THREAD_RUN: case MSG_THREAD_STOP: case MSG_THREAD_STEP_OVER: case MSG_THREAD_STEP_INTO: case MSG_THREAD_STEP_OUT: if (fActiveThread != NULL && fTraceUpdateRunner == NULL) { fListener->ThreadActionRequested(fActiveThread->ID(), message->what); } break; case MSG_CLEAR_STACK_TRACE: { if (fTraceUpdateRunner != NULL) { _SetActiveStackTrace(NULL); _UpdateRunButtons(); } break; } case MSG_THREAD_STATE_CHANGED: { int32 threadID; if (message->FindInt32("thread", &threadID) != B_OK) break; _HandleThreadStateChanged(threadID); break; } case MSG_THREAD_CPU_STATE_CHANGED: { int32 threadID; if (message->FindInt32("thread", &threadID) != B_OK) break; _HandleCpuStateChanged(threadID); break; } case MSG_THREAD_STACK_TRACE_CHANGED: { int32 threadID; if (message->FindInt32("thread", &threadID) != B_OK) break; _HandleStackTraceChanged(threadID); break; } case MSG_IMAGE_DEBUG_INFO_CHANGED: { int32 imageID; if (message->FindInt32("image", &imageID) != B_OK) break; _HandleImageDebugInfoChanged(imageID); break; } case MSG_CONSOLE_OUTPUT_RECEIVED: { int32 fd; BString output; if (message->FindInt32("fd", &fd) != B_OK || message->FindString("output", &output) != B_OK) { break; } fConsoleOutputView->ConsoleOutputReceived(fd, output); break; } case MSG_USER_BREAKPOINT_CHANGED: { UserBreakpoint* breakpoint; if (message->FindPointer("breakpoint", (void**)&breakpoint) != B_OK) break; BReference<UserBreakpoint> breakpointReference(breakpoint, true); _HandleUserBreakpointChanged(breakpoint); break; } case MSG_WATCHPOINT_CHANGED: { Watchpoint* watchpoint; if (message->FindPointer("watchpoint", (void**)&watchpoint) != B_OK) break; BReference<Watchpoint> watchpointReference(watchpoint, true); _HandleWatchpointChanged(watchpoint); break; } case MSG_FUNCTION_SOURCE_CODE_CHANGED: { _HandleSourceCodeChanged(); break; } default: BWindow::MessageReceived(message); break; } }