1 /*
2 * Copyright 2003-2009, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Jonas Sundström, jonas@kirilla.com
7 */
8
9
10 #include "ZipOMatic.h"
11
12 #include <Alert.h>
13 #include <Roster.h>
14 #include <StringFormat.h>
15 #include <TrackerAddOnAppLaunch.h>
16
17 #include "ZipOMaticMisc.h"
18 #include "ZipOMaticWindow.h"
19
20
21 #undef B_TRANSLATION_CONTEXT
22 #define B_TRANSLATION_CONTEXT "file:ZipOMatic.cpp"
23
24
25 int
main()26 main()
27 {
28 ZipOMatic app;
29 app.Run();
30
31 return 0;
32 }
33
34
ZipOMatic()35 ZipOMatic::ZipOMatic()
36 :
37 BApplication(ZIPOMATIC_APP_SIG),
38 fGotRefs(false),
39 fInvoker(new BInvoker(new BMessage(ZIPPO_QUIT_OR_CONTINUE), NULL, this))
40 {
41 }
42
43
~ZipOMatic()44 ZipOMatic::~ZipOMatic()
45 {
46 }
47
48
49 void
RefsReceived(BMessage * message)50 ZipOMatic::RefsReceived(BMessage* message)
51 {
52 entry_ref ref;
53 if (message->FindRef("refs", &ref) == B_OK) {
54 _UseExistingOrCreateNewWindow(message);
55 fGotRefs = true;
56 } else if (!IsLaunching()) {
57 PostMessage(B_SILENT_RELAUNCH);
58 }
59 }
60
61
62 void
ReadyToRun()63 ZipOMatic::ReadyToRun()
64 {
65 if (!fGotRefs)
66 _UseExistingOrCreateNewWindow();
67 }
68
69
70 void
MessageReceived(BMessage * message)71 ZipOMatic::MessageReceived(BMessage* message)
72 {
73 switch (message->what) {
74 case ZIPPO_WINDOW_QUIT:
75 {
76 snooze(200000);
77 if (CountWindows() == 0)
78 Quit();
79 break;
80 }
81 case B_SILENT_RELAUNCH:
82 _SilentRelaunch();
83 break;
84
85 case ZIPPO_QUIT_OR_CONTINUE:
86 {
87 int32 button;
88 if (message->FindInt32("which", &button) == B_OK) {
89 if (button == 0) {
90 _StopZipping();
91 } else {
92 if (CountWindows() == 0)
93 Quit();
94 }
95 }
96 break;
97 }
98
99 default:
100 BApplication::MessageReceived(message);
101 break;
102 }
103 }
104
105
106 bool
QuitRequested(void)107 ZipOMatic::QuitRequested(void)
108 {
109 if (CountWindows() <= 0)
110 return true;
111
112 BWindow* window;
113 ZippoWindow* zippo;
114 ZippoWindow* lastFoundZippo = NULL;
115 int32 zippoCount = 0;
116
117 for (int32 i = 0;; i++) {
118 window = WindowAt(i);
119 if (window == NULL)
120 break;
121
122 zippo = dynamic_cast<ZippoWindow*>(window);
123 if (zippo == NULL)
124 continue;
125
126 lastFoundZippo = zippo;
127
128 if (zippo->Lock()) {
129 if (zippo->IsZipping())
130 zippoCount++;
131 else
132 zippo->PostMessage(B_QUIT_REQUESTED);
133
134 zippo->Unlock();
135 }
136 }
137
138 if (zippoCount == 1) {
139 // This is likely the most frequent case - a single zipper.
140 // We post a message to the window so it can put up its own
141 // BAlert instead of the app-wide BAlert. This avoids making
142 // a difference between having pressed Commmand-W or Command-Q.
143 // Closing or quitting, it doesn't matter for a single window.
144
145 if (lastFoundZippo->Lock()) {
146 lastFoundZippo->Activate();
147 lastFoundZippo->PostMessage(B_QUIT_REQUESTED);
148 lastFoundZippo->Unlock();
149 }
150 return false;
151 }
152
153 if (zippoCount > 0) {
154 // The multi-zipper case differs from the single-zipper case
155 // in that zippers are not paused while the BAlert is up.
156
157 static BStringFormat format(
158 B_TRANSLATE("You have {0, plural, one{# Zip-O-Matic} "
159 "other{# Zip-O-Matics}} running.\n\n"));
160
161 BString question;
162
163 format.Format(question, zippoCount);
164
165 question << B_TRANSLATE("Do you want to stop them?");
166
167 BAlert* alert = new BAlert(NULL, question.String(),
168 B_TRANSLATE("Stop them"), B_TRANSLATE("Let them continue"), NULL,
169 B_WIDTH_AS_USUAL, B_WARNING_ALERT);
170 alert->Go(fInvoker);
171 alert->Activate();
172 // BAlert, being modal, does not show on the current workspace
173 // if the application has no window there. Activate() triggers
174 // a switch to a workspace where it does have a window.
175
176 // TODO: See if AS_ACTIVATE_WINDOW should be handled differently
177 // in src/servers/app/Desktop.cpp Desktop::ActivateWindow()
178 // or if maybe BAlert should (and does not?) activate itself.
179
180 return false;
181 }
182
183 if (CountWindows() <= 0)
184 return true;
185
186 return false;
187 }
188
189
190 void
_SilentRelaunch()191 ZipOMatic::_SilentRelaunch()
192 {
193 _UseExistingOrCreateNewWindow();
194 }
195
196
197 void
_UseExistingOrCreateNewWindow(BMessage * message)198 ZipOMatic::_UseExistingOrCreateNewWindow(BMessage* message)
199 {
200 int32 windowCount = 0;
201 BWindow* bWindow;
202 ZippoWindow* zWindow;
203 BList list;
204
205 while (1) {
206 bWindow = WindowAt(windowCount++);
207 if (bWindow == NULL)
208 break;
209
210 zWindow = dynamic_cast<ZippoWindow*>(bWindow);
211 if (zWindow == NULL)
212 continue;
213
214 list.AddItem(zWindow);
215
216 if (zWindow->Lock()) {
217 if (!zWindow->IsZipping()) {
218 if (message != NULL)
219 zWindow->PostMessage(message);
220 zWindow->SetWorkspaces(B_CURRENT_WORKSPACE);
221 zWindow->Activate();
222 zWindow->Unlock();
223 return;
224 }
225 zWindow->Unlock();
226 }
227 }
228
229 if (message) {
230 zWindow = new ZippoWindow(list);
231 zWindow->PostMessage(message);
232 } else {
233 zWindow = new ZippoWindow(list, true);
234 }
235
236 zWindow->Show();
237 }
238
239
240 void
_StopZipping()241 ZipOMatic::_StopZipping()
242 {
243 BWindow* window;
244 ZippoWindow* zippo;
245 BList list;
246
247 for (int32 i = 0;; i++) {
248 window = WindowAt(i);
249 if (window == NULL)
250 break;
251
252 zippo = dynamic_cast<ZippoWindow*>(window);
253 if (zippo == NULL)
254 continue;
255
256 list.AddItem(zippo);
257 }
258
259 for (int32 i = 0;; i++) {
260 zippo = static_cast<ZippoWindow*>(list.ItemAt(i));
261 if (zippo == NULL)
262 break;
263
264 if (zippo->Lock()) {
265 if (zippo->IsZipping())
266 zippo->StopZipping();
267
268 zippo->PostMessage(B_QUIT_REQUESTED);
269 zippo->Unlock();
270 }
271 }
272 }
273
274