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 26 main() 27 { 28 ZipOMatic app; 29 app.Run(); 30 31 return 0; 32 } 33 34 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 44 ZipOMatic::~ZipOMatic() 45 { 46 } 47 48 49 void 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 63 ZipOMatic::ReadyToRun() 64 { 65 if (!fGotRefs) 66 _UseExistingOrCreateNewWindow(); 67 } 68 69 70 void 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 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 191 ZipOMatic::_SilentRelaunch() 192 { 193 _UseExistingOrCreateNewWindow(); 194 } 195 196 197 void 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 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