xref: /haiku/src/apps/debugger/user_interface/gui/utility_windows/SignalDispositionEditWindow.cpp (revision 10ba334855ad0d7297e23f15dea292f7dbdd231c)
1b3f2ebf0SRene Gollent /*
2*10ba3348SRene Gollent  * Copyright 2015-2016, Rene Gollent, rene@gollent.com.
3b3f2ebf0SRene Gollent  * Distributed under the terms of the MIT License.
4b3f2ebf0SRene Gollent  */
5b3f2ebf0SRene Gollent #include "SignalDispositionEditWindow.h"
6b3f2ebf0SRene Gollent 
7b3f2ebf0SRene Gollent #include <signal.h>
8b3f2ebf0SRene Gollent 
9b3f2ebf0SRene Gollent #include <Button.h>
10b3f2ebf0SRene Gollent #include <LayoutBuilder.h>
11b3f2ebf0SRene Gollent #include <MenuField.h>
12b3f2ebf0SRene Gollent 
13b3f2ebf0SRene Gollent #include <AutoDeleter.h>
14b3f2ebf0SRene Gollent #include <AutoLocker.h>
15b3f2ebf0SRene Gollent 
16*10ba3348SRene Gollent #include "AppMessageCodes.h"
17b3f2ebf0SRene Gollent #include "SignalDispositionMenu.h"
18b3f2ebf0SRene Gollent #include "SignalDispositionTypes.h"
19*10ba3348SRene Gollent #include "Team.h"
20b3f2ebf0SRene Gollent #include "UiUtils.h"
21b3f2ebf0SRene Gollent #include "UserInterface.h"
22b3f2ebf0SRene Gollent 
23b3f2ebf0SRene Gollent 
24b3f2ebf0SRene Gollent enum {
25b3f2ebf0SRene Gollent 	MSG_SELECTED_SIGNAL_CHANGED 		= 'ssic',
26b3f2ebf0SRene Gollent 	MSG_SELECTED_DISPOSITION_CHANGED 	= 'sdic',
27b3f2ebf0SRene Gollent 	MSG_SAVE_SIGNAL_DISPOSITION 		= 'ssid'
28b3f2ebf0SRene Gollent };
29b3f2ebf0SRene Gollent 
30b3f2ebf0SRene Gollent 
SignalDispositionEditWindow(::Team * team,int32 signal,UserInterfaceListener * listener,BHandler * target)31b3f2ebf0SRene Gollent SignalDispositionEditWindow::SignalDispositionEditWindow(::Team* team,
32b3f2ebf0SRene Gollent 	int32 signal, UserInterfaceListener* listener, BHandler* target)
33b3f2ebf0SRene Gollent 	:
3432b9dee4SRene Gollent 	BWindow(BRect(), "Edit signal disposition", B_FLOATING_WINDOW,
35b3f2ebf0SRene Gollent 		B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
36b3f2ebf0SRene Gollent 	fTeam(team),
37b3f2ebf0SRene Gollent 	fListener(listener),
38b3f2ebf0SRene Gollent 	fEditMode(signal > 0),
39b3f2ebf0SRene Gollent 	fCurrentSignal(signal),
40b3f2ebf0SRene Gollent 	fSaveButton(NULL),
41b3f2ebf0SRene Gollent 	fCancelButton(NULL),
42b3f2ebf0SRene Gollent 	fSignalSelectionField(NULL),
43b3f2ebf0SRene Gollent 	fDispositionSelectionField(NULL),
44b3f2ebf0SRene Gollent 	fTarget(target)
45b3f2ebf0SRene Gollent {
46b3f2ebf0SRene Gollent }
47b3f2ebf0SRene Gollent 
48b3f2ebf0SRene Gollent 
~SignalDispositionEditWindow()49b3f2ebf0SRene Gollent SignalDispositionEditWindow::~SignalDispositionEditWindow()
50b3f2ebf0SRene Gollent {
51b3f2ebf0SRene Gollent 	BMessenger(fTarget).SendMessage(MSG_SIGNAL_DISPOSITION_EDIT_WINDOW_CLOSED);
52b3f2ebf0SRene Gollent }
53b3f2ebf0SRene Gollent 
54b3f2ebf0SRene Gollent 
55b3f2ebf0SRene Gollent SignalDispositionEditWindow*
Create(::Team * team,int32 signal,UserInterfaceListener * listener,BHandler * target)56b3f2ebf0SRene Gollent SignalDispositionEditWindow::Create(::Team* team, int32 signal,
57b3f2ebf0SRene Gollent 	UserInterfaceListener* listener, BHandler* target)
58b3f2ebf0SRene Gollent {
59b3f2ebf0SRene Gollent 	SignalDispositionEditWindow* self = new SignalDispositionEditWindow(
60b3f2ebf0SRene Gollent 		team, signal, listener, target);
61b3f2ebf0SRene Gollent 
62b3f2ebf0SRene Gollent 	try {
63b3f2ebf0SRene Gollent 		self->_Init();
64b3f2ebf0SRene Gollent 	} catch (...) {
65b3f2ebf0SRene Gollent 		delete self;
66b3f2ebf0SRene Gollent 		throw;
67b3f2ebf0SRene Gollent 	}
68b3f2ebf0SRene Gollent 
69b3f2ebf0SRene Gollent 	return self;
70b3f2ebf0SRene Gollent 
71b3f2ebf0SRene Gollent }
72b3f2ebf0SRene Gollent 
73b3f2ebf0SRene Gollent void
MessageReceived(BMessage * message)74b3f2ebf0SRene Gollent SignalDispositionEditWindow::MessageReceived(BMessage* message)
75b3f2ebf0SRene Gollent {
76b3f2ebf0SRene Gollent 	switch (message->what) {
77b3f2ebf0SRene Gollent 		case MSG_SELECTED_SIGNAL_CHANGED:
78b3f2ebf0SRene Gollent 		{
79b3f2ebf0SRene Gollent 			int32 signal;
80b3f2ebf0SRene Gollent 			if (message->FindInt32("signal", &signal) == B_OK)
81b3f2ebf0SRene Gollent 				fCurrentSignal = signal;
82b3f2ebf0SRene Gollent 			break;
83b3f2ebf0SRene Gollent 		}
84b3f2ebf0SRene Gollent 		case MSG_SELECTED_DISPOSITION_CHANGED:
85b3f2ebf0SRene Gollent 		{
86b3f2ebf0SRene Gollent 			int32 disposition;
87b3f2ebf0SRene Gollent 			if (message->FindInt32("disposition", &disposition) == B_OK)
88b3f2ebf0SRene Gollent 				fCurrentDisposition = disposition;
89b3f2ebf0SRene Gollent 			break;
90b3f2ebf0SRene Gollent 		}
91b3f2ebf0SRene Gollent 		case MSG_SAVE_SIGNAL_DISPOSITION:
92b3f2ebf0SRene Gollent 		{
93b3f2ebf0SRene Gollent 			fListener->SetCustomSignalDispositionRequested(fCurrentSignal,
94b3f2ebf0SRene Gollent 				fCurrentDisposition);
95b3f2ebf0SRene Gollent 			// fall through
96b3f2ebf0SRene Gollent 		}
97b3f2ebf0SRene Gollent 		case B_CANCEL:
98b3f2ebf0SRene Gollent 			Quit();
99b3f2ebf0SRene Gollent 			break;
100b3f2ebf0SRene Gollent 
101b3f2ebf0SRene Gollent 		default:
102b3f2ebf0SRene Gollent 			BWindow::MessageReceived(message);
103b3f2ebf0SRene Gollent 			break;
104b3f2ebf0SRene Gollent 	}
105b3f2ebf0SRene Gollent 
106b3f2ebf0SRene Gollent }
107b3f2ebf0SRene Gollent 
108b3f2ebf0SRene Gollent 
109b3f2ebf0SRene Gollent void
Show()110b3f2ebf0SRene Gollent SignalDispositionEditWindow::Show()
111b3f2ebf0SRene Gollent {
112b3f2ebf0SRene Gollent 	CenterOnScreen();
113b3f2ebf0SRene Gollent 	BWindow::Show();
114b3f2ebf0SRene Gollent }
115b3f2ebf0SRene Gollent 
116b3f2ebf0SRene Gollent 
117b3f2ebf0SRene Gollent void
_Init()118b3f2ebf0SRene Gollent SignalDispositionEditWindow::_Init()
119b3f2ebf0SRene Gollent {
120b3f2ebf0SRene Gollent 	SignalDispositionMenu* menu = new SignalDispositionMenu("dispositionMenu",
121b3f2ebf0SRene Gollent 		new BMessage(MSG_SELECTED_DISPOSITION_CHANGED));
122b3f2ebf0SRene Gollent 
123b3f2ebf0SRene Gollent 	BLayoutBuilder::Group<>(this, B_VERTICAL)
124b3f2ebf0SRene Gollent 		.SetInsets(B_USE_DEFAULT_SPACING)
125b3f2ebf0SRene Gollent 		.AddGroup(B_HORIZONTAL)
126b3f2ebf0SRene Gollent 			.Add((fSignalSelectionField = new BMenuField("Signal:",
127b3f2ebf0SRene Gollent 				_BuildSignalSelectionMenu())))
128b3f2ebf0SRene Gollent 			.Add((fDispositionSelectionField = new BMenuField("Disposition:",
129b3f2ebf0SRene Gollent 				menu)))
130b3f2ebf0SRene Gollent 		.End()
131b3f2ebf0SRene Gollent 		.AddGroup(B_HORIZONTAL)
132b3f2ebf0SRene Gollent 			.AddGlue()
133b3f2ebf0SRene Gollent 			.Add((fSaveButton = new BButton("Save",
134b3f2ebf0SRene Gollent 				new BMessage(MSG_SAVE_SIGNAL_DISPOSITION))))
135b3f2ebf0SRene Gollent 			.Add((fCancelButton = new BButton("Cancel",
136b3f2ebf0SRene Gollent 				new BMessage(B_CANCEL))))
137b3f2ebf0SRene Gollent 		.End()
138b3f2ebf0SRene Gollent 	.End();
139b3f2ebf0SRene Gollent 
140b3f2ebf0SRene Gollent 	fSignalSelectionField->Menu()->SetLabelFromMarked(true);
141b3f2ebf0SRene Gollent 	fSignalSelectionField->Menu()->SetTargetForItems(this);
142b3f2ebf0SRene Gollent 	menu->SetLabelFromMarked(true);
143b3f2ebf0SRene Gollent 	menu->SetTargetForItems(this);
144b3f2ebf0SRene Gollent 
145b3f2ebf0SRene Gollent 	AutoLocker< ::Team> teamLocker(fTeam);
146b3f2ebf0SRene Gollent 	_UpdateState();
147b3f2ebf0SRene Gollent 
148b3f2ebf0SRene Gollent 	// if we're editing an existing row, don't allow changing the signal
149b3f2ebf0SRene Gollent 	// selection
150b3f2ebf0SRene Gollent 	if (fEditMode)
151b3f2ebf0SRene Gollent 		fSignalSelectionField->SetEnabled(false);
152b3f2ebf0SRene Gollent 
153b3f2ebf0SRene Gollent 
154b3f2ebf0SRene Gollent }
155b3f2ebf0SRene Gollent 
156b3f2ebf0SRene Gollent 
157b3f2ebf0SRene Gollent BMenu*
_BuildSignalSelectionMenu()158b3f2ebf0SRene Gollent SignalDispositionEditWindow::_BuildSignalSelectionMenu()
159b3f2ebf0SRene Gollent {
160b3f2ebf0SRene Gollent 	BMenu* menu = new BMenu("signals");
161b3f2ebf0SRene Gollent 	BMenuItem* item;
162b3f2ebf0SRene Gollent 
163b3f2ebf0SRene Gollent 	#undef ADD_SIGNAL_MENU_ITEM
164b3f2ebf0SRene Gollent 	#define ADD_SIGNAL_MENU_ITEM(x)										\
165b3f2ebf0SRene Gollent 		menu->AddItem((item = new BMenuItem(#x, new BMessage(			\
166b3f2ebf0SRene Gollent 			MSG_SELECTED_SIGNAL_CHANGED))));							\
167b3f2ebf0SRene Gollent 		item->Message()->AddInt32("signal", x);
168b3f2ebf0SRene Gollent 
169b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGHUP)
170b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGINT)
171b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGQUIT)
172b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGILL)
173b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGCHLD)
174b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGABRT)
175b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGPIPE)
176b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGFPE)
177b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGKILL)
178b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGSTOP)
179b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGSEGV)
180b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGCONT)
181b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGTSTP)
182b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGALRM)
183b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGTERM)
184b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGTTIN)
185b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGTTOU)
186b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGUSR1)
187b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGUSR2)
188b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGWINCH)
189b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGKILLTHR)
190b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGTRAP)
191b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGPOLL)
192b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGPROF)
193b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGSYS)
194b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGURG)
195b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGVTALRM)
196b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGXCPU)
197b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGXFSZ)
198b3f2ebf0SRene Gollent 	ADD_SIGNAL_MENU_ITEM(SIGBUS)
199b3f2ebf0SRene Gollent 
200b3f2ebf0SRene Gollent 	BString signalName;
201b3f2ebf0SRene Gollent 	for (int32 i = SIGRTMIN; i <= SIGRTMAX; i++) {
202b3f2ebf0SRene Gollent 		menu->AddItem((item = new BMenuItem(UiUtils::SignalNameToString(i,
203b3f2ebf0SRene Gollent 					signalName), new BMessage(MSG_SELECTED_SIGNAL_CHANGED))));
204b3f2ebf0SRene Gollent 		item->Message()->AddInt32("signal", i);
205b3f2ebf0SRene Gollent 	}
206b3f2ebf0SRene Gollent 
207b3f2ebf0SRene Gollent 	return menu;
208b3f2ebf0SRene Gollent }
209b3f2ebf0SRene Gollent 
210b3f2ebf0SRene Gollent 
211b3f2ebf0SRene Gollent void
_UpdateState()212b3f2ebf0SRene Gollent SignalDispositionEditWindow::_UpdateState()
213b3f2ebf0SRene Gollent {
214b3f2ebf0SRene Gollent 	if (fCurrentSignal <= 0)
215b3f2ebf0SRene Gollent 		fCurrentSignal = SIGHUP;
216b3f2ebf0SRene Gollent 
217b3f2ebf0SRene Gollent 	fSignalSelectionField->Menu()->ItemAt(fCurrentSignal - 1)->SetMarked(true);
218b3f2ebf0SRene Gollent 
219b3f2ebf0SRene Gollent 	fCurrentDisposition = fTeam->SignalDispositionFor(fCurrentSignal);
220b3f2ebf0SRene Gollent 	fDispositionSelectionField->Menu()->ItemAt(fCurrentDisposition)->SetMarked(
221b3f2ebf0SRene Gollent 		true);
222b3f2ebf0SRene Gollent }
223b3f2ebf0SRene Gollent 
224