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