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