Add "Run to cursor" context action.
- UserInterfaceListener/TeamDebugger: Extend ThreadActionRequested() to allow passing a target address. Adjust TeamDebugger's implementation accordingly. - ThreadHandler: The MSG_THREAD_RUN action can now optionally take an address parameter to run until. If this is specified, set a temporary breakpoint for said address before resuming execution. - SourceView: On right click, present a context menu showing possible actions for the current line if we're currently in a stopped thread. For the moment, this only yields the "Run to cursor" action, but more will be added in the future.
This commit is contained in:
@@ -16,9 +16,11 @@
|
||||
#include <Clipboard.h>
|
||||
#include <LayoutUtils.h>
|
||||
#include <Looper.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Message.h>
|
||||
#include <MessageRunner.h>
|
||||
#include <Polygon.h>
|
||||
#include <PopUpMenu.h>
|
||||
#include <Region.h>
|
||||
#include <ScrollBar.h>
|
||||
#include <ScrollView.h>
|
||||
@@ -27,6 +29,7 @@
|
||||
#include <AutoLocker.h>
|
||||
#include <ObjectList.h>
|
||||
|
||||
#include "AutoDeleter.h"
|
||||
#include "Breakpoint.h"
|
||||
#include "DisassembledCode.h"
|
||||
#include "Function.h"
|
||||
@@ -918,18 +921,11 @@ SourceView::MarkerView::MouseDown(BPoint where)
|
||||
return;
|
||||
|
||||
int32 line = LineAtOffset(where.y);
|
||||
if (line < 0)
|
||||
return;
|
||||
|
||||
AutoLocker<Team> locker(fTeam);
|
||||
Statement* statement;
|
||||
if (fTeam->GetStatementAtSourceLocation(fSourceCode,
|
||||
SourceLocation(line), statement) != B_OK) {
|
||||
if (!fSourceView->GetStatementForLine(line, statement))
|
||||
return;
|
||||
}
|
||||
BReference<Statement> statementReference(statement, true);
|
||||
if (statement->StartSourceLocation().Line() != line)
|
||||
return;
|
||||
|
||||
int32 modifiers;
|
||||
if (Looper()->CurrentMessage()->FindInt32("modifiers", &modifiers) != B_OK)
|
||||
@@ -1193,7 +1189,15 @@ SourceView::TextView::MessageReceived(BMessage* message)
|
||||
void
|
||||
SourceView::TextView::MouseDown(BPoint where)
|
||||
{
|
||||
if (fSourceCode != NULL) {
|
||||
if (fSourceCode == NULL)
|
||||
return;
|
||||
|
||||
int32 buttons;
|
||||
if (Looper()->CurrentMessage()->FindInt32("buttons", &buttons) != B_OK)
|
||||
buttons = B_PRIMARY_MOUSE_BUTTON;
|
||||
|
||||
|
||||
if (buttons == B_PRIMARY_MOUSE_BUTTON) {
|
||||
if (!IsFocus())
|
||||
MakeFocus(true);
|
||||
fTrackState = kTracking;
|
||||
@@ -1233,6 +1237,57 @@ SourceView::TextView::MouseDown(BPoint where)
|
||||
Invalidate();
|
||||
SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
|
||||
}
|
||||
} else if (buttons == B_SECONDARY_MOUSE_BUTTON) {
|
||||
int32 line = LineAtOffset(where.y);
|
||||
if (line < 0)
|
||||
return;
|
||||
|
||||
::Team* team = fSourceView->fTeam;
|
||||
AutoLocker<Team> locker(team);
|
||||
::Thread* activeThread = fSourceView->fActiveThread;
|
||||
|
||||
if (activeThread == NULL)
|
||||
return;
|
||||
else if (activeThread->State() != THREAD_STATE_STOPPED)
|
||||
return;
|
||||
|
||||
Statement* statement;
|
||||
if (!fSourceView->GetStatementForLine(line, statement))
|
||||
return;
|
||||
BReference<Statement> statementReference(statement, true);
|
||||
|
||||
BPopUpMenu* menu = new(std::nothrow) BPopUpMenu("");
|
||||
if (menu == NULL)
|
||||
return;
|
||||
ObjectDeleter<BPopUpMenu> menuDeleter(menu);
|
||||
|
||||
BMessage* message = new(std::nothrow) BMessage(MSG_THREAD_RUN);
|
||||
if (message == NULL)
|
||||
return;
|
||||
ObjectDeleter<BMessage> messageDeleter(message);
|
||||
|
||||
message->AddUInt64("address", statement->CoveringAddressRange()
|
||||
.Start());
|
||||
BMenuItem* item = new(std::nothrow) BMenuItem("Run to cursor",
|
||||
message);
|
||||
if (item == NULL)
|
||||
return;
|
||||
ObjectDeleter<BMenuItem> itemDeleter(item);
|
||||
messageDeleter.Detach();
|
||||
|
||||
if (!menu->AddItem(item))
|
||||
return;
|
||||
|
||||
itemDeleter.Detach();
|
||||
messageDeleter.Detach();
|
||||
menuDeleter.Detach();
|
||||
|
||||
BPoint screenWhere(where);
|
||||
ConvertToScreen(&screenWhere);
|
||||
menu->SetTargetForItems(fSourceView);
|
||||
BRect mouseRect(screenWhere, screenWhere);
|
||||
mouseRect.InsetBy(-4.0, -4.0);
|
||||
menu->Go(screenWhere, true, false, mouseRect, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1695,6 +1750,7 @@ SourceView::SourceView(Team* team, Listener* listener)
|
||||
:
|
||||
BView("source view", 0),
|
||||
fTeam(team),
|
||||
fActiveThread(NULL),
|
||||
fStackTrace(NULL),
|
||||
fStackFrame(NULL),
|
||||
fSourceCode(NULL),
|
||||
@@ -1713,7 +1769,7 @@ SourceView::SourceView(Team* team, Listener* listener)
|
||||
SourceView::~SourceView()
|
||||
{
|
||||
SetStackFrame(NULL);
|
||||
SetStackTrace(NULL);
|
||||
SetStackTrace(NULL, NULL);
|
||||
SetSourceCode(NULL);
|
||||
}
|
||||
|
||||
@@ -1734,6 +1790,27 @@ SourceView::Create(Team* team, Listener* listener)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch(message->what) {
|
||||
case MSG_THREAD_RUN:
|
||||
{
|
||||
target_addr_t address;
|
||||
if (message->FindUInt64("address", &address) != B_OK)
|
||||
break;
|
||||
fListener->ThreadActionRequested(fActiveThread, message->what,
|
||||
address);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BView::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceView::UnsetListener()
|
||||
{
|
||||
@@ -1742,13 +1819,21 @@ SourceView::UnsetListener()
|
||||
|
||||
|
||||
void
|
||||
SourceView::SetStackTrace(StackTrace* stackTrace)
|
||||
SourceView::SetStackTrace(StackTrace* stackTrace, Thread* activeThread)
|
||||
{
|
||||
TRACE_GUI("SourceView::SetStackTrace(%p)\n", stackTrace);
|
||||
|
||||
if (stackTrace == fStackTrace)
|
||||
return;
|
||||
|
||||
if (fActiveThread != NULL)
|
||||
fActiveThread->ReleaseReference();
|
||||
|
||||
fActiveThread = activeThread;
|
||||
|
||||
if (fActiveThread != NULL)
|
||||
fActiveThread->AcquireReference();
|
||||
|
||||
if (fStackTrace != NULL) {
|
||||
fMarkerManager->SetStackTrace(NULL);
|
||||
fMarkerView->SetStackTrace(NULL);
|
||||
@@ -1949,6 +2034,29 @@ SourceView::DoLayout()
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SourceView::GetStatementForLine(int32 line, Statement*& _statement)
|
||||
{
|
||||
if (line < 0)
|
||||
return false;
|
||||
|
||||
AutoLocker<Team> locker(fTeam);
|
||||
Statement* statement;
|
||||
if (fTeam->GetStatementAtSourceLocation(fSourceCode, SourceLocation(line),
|
||||
statement) != B_OK) {
|
||||
return false;
|
||||
}
|
||||
BReference<Statement> statementReference(statement, true);
|
||||
if (statement->StartSourceLocation().Line() != line)
|
||||
return false;
|
||||
|
||||
_statement = statement;
|
||||
statementReference.Detach();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceView::_Init()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user