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