1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered 30 trademarks of Be Incorporated in the United States and other countries. Other 31 brand product names are registered trademarks or trademarks of their respective 32 holders. 33 All rights reserved. 34 */ 35 36 37 #include "BarApp.h" 38 39 #include <locale.h> 40 #include <strings.h> 41 42 #include <AppFileInfo.h> 43 #include <Autolock.h> 44 #include <Bitmap.h> 45 #include <Catalog.h> 46 #include <Debug.h> 47 #include <Directory.h> 48 #include <Dragger.h> 49 #include <File.h> 50 #include <FindDirectory.h> 51 #include <Locale.h> 52 #include <Mime.h> 53 #include <Message.h> 54 #include <Messenger.h> 55 #include <Path.h> 56 #include <Roster.h> 57 #include <RosterPrivate.h> 58 59 #include "BarView.h" 60 #include "BarWindow.h" 61 #include "DeskbarUtils.h" 62 #include "FSUtils.h" 63 #include "PreferencesWindow.h" 64 #include "ResourceSet.h" 65 #include "StatusView.h" 66 #include "Switcher.h" 67 #include "Utilities.h" 68 69 #include "icons.h" 70 #include "tracker_private.h" 71 72 73 BLocker TBarApp::sSubscriberLock; 74 BList TBarApp::sBarTeamInfoList; 75 BList TBarApp::sSubscribers; 76 77 78 const uint32 kShowDeskbarMenu = 'BeMn'; 79 const uint32 kShowTeamMenu = 'TmMn'; 80 81 static const color_space kIconColorSpace = B_RGBA32; 82 83 84 int 85 main() 86 { 87 setlocale(LC_ALL, ""); 88 TBarApp app; 89 app.Run(); 90 91 return B_OK; 92 } 93 94 95 TBarApp::TBarApp() 96 : 97 BApplication(kDeskbarSignature), 98 fSettingsFile(NULL), 99 fClockSettingsFile(NULL), 100 fPreferencesWindow(NULL) 101 { 102 InitSettings(); 103 InitIconPreloader(); 104 105 fBarWindow = new TBarWindow(); 106 fBarView = fBarWindow->BarView(); 107 108 be_roster->StartWatching(this); 109 110 gLocalizedNamePreferred 111 = BLocaleRoster::Default()->IsFilesystemTranslationPreferred(); 112 113 sBarTeamInfoList.MakeEmpty(); 114 115 BList teamList; 116 int32 numTeams; 117 be_roster->GetAppList(&teamList); 118 numTeams = teamList.CountItems(); 119 for (int32 i = 0; i < numTeams; i++) { 120 app_info appInfo; 121 team_id tID = (addr_t)teamList.ItemAt(i); 122 if (be_roster->GetRunningAppInfo(tID, &appInfo) == B_OK) { 123 AddTeam(appInfo.team, appInfo.flags, appInfo.signature, 124 &appInfo.ref); 125 } 126 } 127 128 sSubscribers.MakeEmpty(); 129 fSwitcherMessenger = BMessenger(new TSwitchManager(fSettings.switcherLoc)); 130 fBarWindow->Show(); 131 132 fBarWindow->Lock(); 133 fBarView->UpdatePlacement(); 134 fBarWindow->Unlock(); 135 136 // this messenger now targets the barview instead of the 137 // statusview so that all additions to the tray 138 // follow the same path 139 fStatusViewMessenger = BMessenger(fBarWindow->FindView("BarView")); 140 } 141 142 143 TBarApp::~TBarApp() 144 { 145 be_roster->StopWatching(this); 146 147 int32 teamCount = sBarTeamInfoList.CountItems(); 148 for (int32 i = 0; i < teamCount; i++) { 149 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 150 delete barInfo; 151 } 152 153 int32 subsCount = sSubscribers.CountItems(); 154 for (int32 i = 0; i < subsCount; i++) { 155 BMessenger* messenger 156 = static_cast<BMessenger*>(sSubscribers.ItemAt(i)); 157 delete messenger; 158 } 159 160 SaveSettings(); 161 162 delete fSettingsFile; 163 delete fClockSettingsFile; 164 } 165 166 167 bool 168 TBarApp::QuitRequested() 169 { 170 // don't allow the user to quit 171 if (CurrentMessage() && CurrentMessage()->FindBool("shortcut")) { 172 // but close the preferences window 173 QuitPreferencesWindow(); 174 return false; 175 } 176 177 // system quitting, call inherited to notify all loopers 178 fBarWindow->SaveSettings(); 179 BApplication::QuitRequested(); 180 return true; 181 } 182 183 184 void 185 TBarApp::SaveSettings() 186 { 187 if (fSettingsFile->InitCheck() == B_OK) { 188 fSettingsFile->Seek(0, SEEK_SET); 189 BMessage prefs; 190 prefs.AddBool("vertical", fSettings.vertical); 191 prefs.AddBool("left", fSettings.left); 192 prefs.AddBool("top", fSettings.top); 193 prefs.AddInt32("state", fSettings.state); 194 prefs.AddFloat("width", fSettings.width); 195 prefs.AddPoint("switcherLoc", fSettings.switcherLoc); 196 prefs.AddBool("showClock", fSettings.showClock); 197 // applications 198 prefs.AddBool("trackerAlwaysFirst", fSettings.trackerAlwaysFirst); 199 prefs.AddBool("sortRunningApps", fSettings.sortRunningApps); 200 prefs.AddBool("superExpando", fSettings.superExpando); 201 prefs.AddBool("expandNewTeams", fSettings.expandNewTeams); 202 prefs.AddBool("hideLabels", fSettings.hideLabels); 203 prefs.AddInt32("iconSize", fSettings.iconSize); 204 // recent items 205 prefs.AddBool("recentDocsEnabled", fSettings.recentDocsEnabled); 206 prefs.AddBool("recentFoldersEnabled", fSettings.recentFoldersEnabled); 207 prefs.AddBool("recentAppsEnabled", fSettings.recentAppsEnabled); 208 prefs.AddInt32("recentDocsCount", fSettings.recentDocsCount); 209 prefs.AddInt32("recentFoldersCount", fSettings.recentFoldersCount); 210 prefs.AddInt32("recentAppsCount", fSettings.recentAppsCount); 211 // window 212 prefs.AddBool("alwaysOnTop", fSettings.alwaysOnTop); 213 prefs.AddBool("autoRaise", fSettings.autoRaise); 214 prefs.AddBool("autoHide", fSettings.autoHide); 215 216 prefs.Flatten(fSettingsFile); 217 } 218 219 if (fClockSettingsFile->InitCheck() == B_OK) { 220 fClockSettingsFile->Seek(0, SEEK_SET); 221 BMessage prefs; 222 prefs.AddBool("showSeconds", fClockSettings.showSeconds); 223 prefs.AddBool("showDayOfWeek", fClockSettings.showDayOfWeek); 224 prefs.AddBool("showTimeZone", fClockSettings.showTimeZone); 225 226 prefs.Flatten(fClockSettingsFile); 227 } 228 } 229 230 231 void 232 TBarApp::InitSettings() 233 { 234 desk_settings settings; 235 settings.vertical = fDefaultSettings.vertical = true; 236 settings.left = fDefaultSettings.left = false; 237 settings.top = fDefaultSettings.top = true; 238 settings.state = fDefaultSettings.state = kExpandoState; 239 settings.width = fDefaultSettings.width = 0; 240 settings.switcherLoc = fDefaultSettings.switcherLoc = BPoint(5000, 5000); 241 settings.showClock = fDefaultSettings.showClock = true; 242 // applications 243 settings.trackerAlwaysFirst = fDefaultSettings.trackerAlwaysFirst = false; 244 settings.sortRunningApps = fDefaultSettings.sortRunningApps = false; 245 settings.superExpando = fDefaultSettings.superExpando = false; 246 settings.expandNewTeams = fDefaultSettings.expandNewTeams = false; 247 settings.hideLabels = fDefaultSettings.hideLabels = false; 248 settings.iconSize = fDefaultSettings.iconSize = kMinimumIconSize; 249 // recent items 250 settings.recentDocsEnabled = fDefaultSettings.recentDocsEnabled = true; 251 settings.recentFoldersEnabled 252 = fDefaultSettings.recentFoldersEnabled = true; 253 settings.recentAppsEnabled = fDefaultSettings.recentAppsEnabled = true; 254 settings.recentDocsCount = fDefaultSettings.recentDocsCount = 10; 255 settings.recentFoldersCount = fDefaultSettings.recentFoldersCount = 10; 256 settings.recentAppsCount = fDefaultSettings.recentAppsCount = 10; 257 // window 258 settings.alwaysOnTop = fDefaultSettings.alwaysOnTop = false; 259 settings.autoRaise = fDefaultSettings.autoRaise = false; 260 settings.autoHide = fDefaultSettings.autoHide = false; 261 262 clock_settings clock; 263 clock.showSeconds = false; 264 clock.showDayOfWeek = false; 265 clock.showTimeZone = false; 266 267 BPath dirPath; 268 const char* settingsFileName = "settings"; 269 const char* clockSettingsFileName = "clock_settings"; 270 271 find_directory(B_USER_DESKBAR_DIRECTORY, &dirPath, true); 272 // just make it 273 274 if (GetDeskbarSettingsDirectory(dirPath, true) == B_OK) { 275 BPath filePath = dirPath; 276 filePath.Append(settingsFileName); 277 fSettingsFile = new BFile(filePath.Path(), O_RDWR); 278 if (fSettingsFile->InitCheck() != B_OK) { 279 BDirectory theDir(dirPath.Path()); 280 if (theDir.InitCheck() == B_OK) 281 theDir.CreateFile(settingsFileName, fSettingsFile); 282 } 283 284 BMessage prefs; 285 if (fSettingsFile->InitCheck() == B_OK 286 && prefs.Unflatten(fSettingsFile) == B_OK) { 287 settings.vertical = prefs.GetBool("vertical", 288 fDefaultSettings.vertical); 289 settings.left = prefs.GetBool("left", 290 fDefaultSettings.left); 291 settings.top = prefs.GetBool("top", 292 fDefaultSettings.top); 293 settings.state = prefs.GetInt32("state", 294 fDefaultSettings.state); 295 settings.width = prefs.GetFloat("width", 296 fDefaultSettings.width); 297 settings.switcherLoc = prefs.GetPoint("switcherLoc", 298 fDefaultSettings.switcherLoc); 299 settings.showClock = prefs.GetBool("showClock", 300 fDefaultSettings.showClock); 301 // applications 302 settings.trackerAlwaysFirst = prefs.GetBool("trackerAlwaysFirst", 303 fDefaultSettings.trackerAlwaysFirst); 304 settings.sortRunningApps = prefs.GetBool("sortRunningApps", 305 fDefaultSettings.sortRunningApps); 306 settings.superExpando = prefs.GetBool("superExpando", 307 fDefaultSettings.superExpando); 308 settings.expandNewTeams = prefs.GetBool("expandNewTeams", 309 fDefaultSettings.expandNewTeams); 310 settings.hideLabels = prefs.GetBool("hideLabels", 311 fDefaultSettings.hideLabels); 312 settings.iconSize = prefs.GetInt32("iconSize", 313 fDefaultSettings.iconSize); 314 // recent items 315 settings.recentDocsEnabled = prefs.GetBool("recentDocsEnabled", 316 fDefaultSettings.recentDocsEnabled); 317 settings.recentFoldersEnabled 318 = prefs.GetBool("recentFoldersEnabled", 319 fDefaultSettings.recentFoldersEnabled); 320 settings.recentAppsEnabled = prefs.GetBool("recentAppsEnabled", 321 fDefaultSettings.recentAppsEnabled); 322 settings.recentDocsCount = prefs.GetInt32("recentDocsCount", 323 fDefaultSettings.recentDocsCount); 324 settings.recentFoldersCount = prefs.GetInt32("recentFoldersCount", 325 fDefaultSettings.recentFoldersCount); 326 settings.recentAppsCount = prefs.GetInt32("recentAppsCount", 327 fDefaultSettings.recentAppsCount); 328 // window 329 settings.alwaysOnTop = prefs.GetBool("alwaysOnTop", 330 fDefaultSettings.alwaysOnTop); 331 settings.autoRaise = prefs.GetBool("autoRaise", 332 fDefaultSettings.autoRaise); 333 settings.autoHide = prefs.GetBool("autoHide", 334 fDefaultSettings.autoHide); 335 } 336 337 filePath = dirPath; 338 filePath.Append(clockSettingsFileName); 339 fClockSettingsFile = new BFile(filePath.Path(), O_RDWR); 340 if (fClockSettingsFile->InitCheck() != B_OK) { 341 BDirectory theDir(dirPath.Path()); 342 if (theDir.InitCheck() == B_OK) 343 theDir.CreateFile(clockSettingsFileName, fClockSettingsFile); 344 } 345 346 if (fClockSettingsFile->InitCheck() == B_OK 347 && prefs.Unflatten(fClockSettingsFile) == B_OK) { 348 clock.showSeconds = prefs.GetBool("showSeconds", false); 349 clock.showDayOfWeek = prefs.GetBool("showDayOfWeek", false); 350 clock.showTimeZone = prefs.GetBool("showTimeZone", false); 351 } 352 } 353 354 fSettings = settings; 355 fClockSettings = clock; 356 } 357 358 359 void 360 TBarApp::MessageReceived(BMessage* message) 361 { 362 switch (message->what) { 363 case 'gloc': 364 case 'sloc': 365 case 'gexp': 366 case 'sexp': 367 case 'info': 368 case 'exst': 369 case 'cwnt': 370 case 'icon': 371 case 'remv': 372 case 'adon': 373 // pass any BDeskbar originating messages on to the window 374 fBarWindow->PostMessage(message); 375 break; 376 377 case kConfigShow: 378 ShowPreferencesWindow(); 379 break; 380 381 case kConfigQuit: 382 QuitPreferencesWindow(); 383 break; 384 385 case kStateChanged: 386 if (fPreferencesWindow != NULL) 387 fPreferencesWindow->PostMessage(kStateChanged); 388 break; 389 390 case kShowDeskbarMenu: 391 if (fBarWindow->Lock()) { 392 fBarWindow->ShowDeskbarMenu(); 393 fBarWindow->Unlock(); 394 } 395 break; 396 397 case kShowTeamMenu: 398 if (fBarWindow->Lock()) { 399 fBarWindow->ShowTeamMenu(); 400 fBarWindow->Unlock(); 401 } 402 break; 403 404 case kUpdateRecentCounts: 405 int32 count; 406 bool enabled; 407 408 if (message->FindInt32("applications", &count) == B_OK) 409 fSettings.recentAppsCount = count; 410 if (message->FindBool("applicationsEnabled", &enabled) == B_OK) 411 fSettings.recentAppsEnabled = enabled && count > 0; 412 413 if (message->FindInt32("folders", &count) == B_OK) 414 fSettings.recentFoldersCount = count; 415 if (message->FindBool("foldersEnabled", &enabled) == B_OK) 416 fSettings.recentFoldersEnabled = enabled && count > 0; 417 418 if (message->FindInt32("documents", &count) == B_OK) 419 fSettings.recentDocsCount = count; 420 if (message->FindBool("documentsEnabled", &enabled) == B_OK) 421 fSettings.recentDocsEnabled = enabled && count > 0; 422 423 if (fPreferencesWindow != NULL) 424 fPreferencesWindow->PostMessage(kUpdatePreferences); 425 break; 426 427 case B_SOME_APP_LAUNCHED: 428 { 429 team_id team = -1; 430 message->FindInt32("be:team", &team); 431 432 uint32 flags = 0; 433 message->FindInt32("be:flags", (int32*)&flags); 434 435 const char* signature = NULL; 436 message->FindString("be:signature", &signature); 437 438 entry_ref ref; 439 message->FindRef("be:ref", &ref); 440 441 AddTeam(team, flags, signature, &ref); 442 break; 443 } 444 445 case B_SOME_APP_QUIT: 446 { 447 team_id team = -1; 448 message->FindInt32("be:team", &team); 449 RemoveTeam(team); 450 break; 451 } 452 453 case B_ARCHIVED_OBJECT: 454 // TODO: what's this??? 455 message->AddString("special", "Alex Osadzinski"); 456 fStatusViewMessenger.SendMessage(message); 457 break; 458 459 case kToggleDraggers: 460 if (BDragger::AreDraggersDrawn()) 461 BDragger::HideAllDraggers(); 462 else 463 BDragger::ShowAllDraggers(); 464 break; 465 466 case kAlwaysTop: 467 fSettings.alwaysOnTop = !fSettings.alwaysOnTop; 468 469 if (fPreferencesWindow != NULL) 470 fPreferencesWindow->PostMessage(kUpdatePreferences); 471 472 fBarWindow->SetFeel(fSettings.alwaysOnTop ? B_FLOATING_ALL_WINDOW_FEEL 473 : B_NORMAL_WINDOW_FEEL); 474 break; 475 476 case kAutoRaise: 477 fSettings.autoRaise = fSettings.alwaysOnTop ? false : 478 !fSettings.autoRaise; 479 480 if (fPreferencesWindow != NULL) 481 fPreferencesWindow->PostMessage(kUpdatePreferences); 482 break; 483 484 case kAutoHide: 485 fSettings.autoHide = !fSettings.autoHide; 486 487 if (fPreferencesWindow != NULL) 488 fPreferencesWindow->PostMessage(kUpdatePreferences); 489 490 fBarWindow->Lock(); 491 fBarView->HideDeskbar(fSettings.autoHide); 492 fBarWindow->Unlock(); 493 break; 494 495 case kTrackerFirst: 496 fSettings.trackerAlwaysFirst = !fSettings.trackerAlwaysFirst; 497 498 if (fPreferencesWindow != NULL) 499 fPreferencesWindow->PostMessage(kUpdatePreferences); 500 501 // if mini mode we don't need to update the view 502 if (fBarView->MiniState()) 503 break; 504 505 fBarWindow->Lock(); 506 fBarView->PlaceApplicationBar(); 507 fBarWindow->Unlock(); 508 break; 509 510 case kSortRunningApps: 511 fSettings.sortRunningApps = !fSettings.sortRunningApps; 512 513 if (fPreferencesWindow != NULL) 514 fPreferencesWindow->PostMessage(kUpdatePreferences); 515 516 // if mini mode we don't need to update the view 517 if (fBarView->MiniState()) 518 break; 519 520 fBarWindow->Lock(); 521 fBarView->PlaceApplicationBar(); 522 fBarWindow->Unlock(); 523 break; 524 525 case kUnsubscribe: 526 { 527 BMessenger messenger; 528 if (message->FindMessenger("messenger", &messenger) == B_OK) 529 Unsubscribe(messenger); 530 break; 531 } 532 533 case kSuperExpando: 534 fSettings.superExpando = !fSettings.superExpando; 535 536 if (fPreferencesWindow != NULL) 537 fPreferencesWindow->PostMessage(kUpdatePreferences); 538 539 // if mini mode we don't need to update the view 540 if (fBarView->MiniState()) 541 break; 542 543 fBarWindow->Lock(); 544 fBarView->PlaceApplicationBar(); 545 fBarWindow->Unlock(); 546 break; 547 548 case kExpandNewTeams: 549 fSettings.expandNewTeams = !fSettings.expandNewTeams; 550 551 if (fPreferencesWindow != NULL) 552 fPreferencesWindow->PostMessage(kUpdatePreferences); 553 554 // if mini mode we don't need to update the view 555 if (fBarView->MiniState()) 556 break; 557 558 fBarWindow->Lock(); 559 fBarView->PlaceApplicationBar(); 560 fBarWindow->Unlock(); 561 break; 562 563 case kHideLabels: 564 fSettings.hideLabels = !fSettings.hideLabels; 565 566 if (fPreferencesWindow != NULL) 567 fPreferencesWindow->PostMessage(kUpdatePreferences); 568 569 // if mini mode we don't need to update the view 570 if (fBarView->MiniState()) 571 break; 572 573 fBarWindow->Lock(); 574 fBarView->PlaceApplicationBar(); 575 fBarWindow->Unlock(); 576 break; 577 578 case kResizeTeamIcons: 579 { 580 int32 oldIconSize = fSettings.iconSize; 581 int32 iconSize; 582 if (message->FindInt32("be:value", &iconSize) != B_OK) 583 break; 584 585 fSettings.iconSize = iconSize * kIconSizeInterval; 586 587 // pin icon size between min and max values 588 if (fSettings.iconSize < kMinimumIconSize) 589 fSettings.iconSize = kMinimumIconSize; 590 else if (fSettings.iconSize > kMaximumIconSize) 591 fSettings.iconSize = kMaximumIconSize; 592 593 // don't resize if icon size hasn't changed 594 if (fSettings.iconSize == oldIconSize) 595 break; 596 597 ResizeTeamIcons(); 598 599 if (fPreferencesWindow != NULL) 600 fPreferencesWindow->PostMessage(kUpdatePreferences); 601 602 // if mini mode we don't need to update the view 603 if (fBarView->MiniState()) 604 break; 605 606 fBarWindow->Lock(); 607 if (!fBarView->Vertical()) { 608 // Must also resize the Deskbar menu and replicant tray in 609 // horizontal mode 610 fBarView->PlaceDeskbarMenu(); 611 fBarView->PlaceTray(false, false); 612 } 613 fBarView->PlaceApplicationBar(); 614 fBarWindow->Unlock(); 615 break; 616 } 617 618 case 'TASK': 619 fSwitcherMessenger.SendMessage(message); 620 break; 621 622 case kSuspendSystem: 623 // TODO: Call BRoster? 624 break; 625 626 case kRebootSystem: 627 case kShutdownSystem: 628 { 629 bool reboot = (message->what == kRebootSystem); 630 bool confirm; 631 message->FindBool("confirm", &confirm); 632 633 BRoster roster; 634 BRoster::Private rosterPrivate(roster); 635 status_t error = rosterPrivate.ShutDown(reboot, confirm, false); 636 if (error != B_OK) 637 fprintf(stderr, "Shutdown failed: %s\n", strerror(error)); 638 639 break; 640 } 641 642 case kShowSplash: 643 run_be_about(); 644 break; 645 646 case kRestartTracker: 647 { 648 BRoster roster; 649 roster.Launch(kTrackerSignature); 650 break; 651 } 652 653 case B_LOCALE_CHANGED: 654 { 655 BLocaleRoster::Default()->Refresh(); 656 657 bool localize; 658 if (message->FindBool("filesys", &localize) == B_OK) 659 gLocalizedNamePreferred = localize; 660 } 661 // fall-through 662 663 case kShowHideTime: 664 case kShowSeconds: 665 case kShowDayOfWeek: 666 case kShowTimeZone: 667 case kGetClockSettings: 668 fStatusViewMessenger.SendMessage(message); 669 // Notify the replicant tray (through BarView) that the time 670 // interval has changed and it should update the time view 671 // and reflow the tray icons. 672 break; 673 674 default: 675 BApplication::MessageReceived(message); 676 break; 677 } 678 } 679 680 681 void 682 TBarApp::RefsReceived(BMessage* refs) 683 { 684 entry_ref ref; 685 for (int32 i = 0; refs->FindRef("refs", i, &ref) == B_OK; i++) { 686 BMessage refsReceived(B_REFS_RECEIVED); 687 refsReceived.AddRef("refs", &ref); 688 689 BEntry entry(&ref); 690 if (!entry.IsDirectory()) 691 TrackerLaunch(&refsReceived, false); 692 } 693 } 694 695 696 void 697 TBarApp::Subscribe(const BMessenger &subscriber, BList* list) 698 { 699 // called when ExpandoMenuBar, TeamMenu or Switcher are built/rebuilt 700 list->MakeEmpty(); 701 702 BAutolock autolock(sSubscriberLock); 703 if (!autolock.IsLocked()) 704 return; 705 706 int32 numTeams = sBarTeamInfoList.CountItems(); 707 for (int32 i = 0; i < numTeams; i++) { 708 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 709 BarTeamInfo* newBarInfo = new (std::nothrow) BarTeamInfo(*barInfo); 710 if (newBarInfo != NULL) 711 list->AddItem(newBarInfo); 712 } 713 714 int32 subsCount = sSubscribers.CountItems(); 715 for (int32 i = 0; i < subsCount; i++) { 716 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 717 if (*messenger == subscriber) 718 return; 719 } 720 721 sSubscribers.AddItem(new BMessenger(subscriber)); 722 } 723 724 725 void 726 TBarApp::Unsubscribe(const BMessenger &subscriber) 727 { 728 BAutolock autolock(sSubscriberLock); 729 if (!autolock.IsLocked()) 730 return; 731 732 int32 count = sSubscribers.CountItems(); 733 for (int32 i = 0; i < count; i++) { 734 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 735 if (*messenger == subscriber) { 736 sSubscribers.RemoveItem(i); 737 delete messenger; 738 break; 739 } 740 } 741 } 742 743 744 void 745 TBarApp::AddTeam(team_id team, uint32 flags, const char* sig, entry_ref* ref) 746 { 747 if ((flags & B_BACKGROUND_APP) != 0 748 || strcasecmp(sig, kDeskbarSignature) == 0) { 749 // don't add if a background app or Deskbar itself 750 return; 751 } 752 753 BAutolock autolock(sSubscriberLock); 754 if (!autolock.IsLocked()) 755 return; 756 757 // have we already seen this team, is this another instance of 758 // a known app? 759 BarTeamInfo* multiLaunchTeam = NULL; 760 int32 teamCount = sBarTeamInfoList.CountItems(); 761 for (int32 i = 0; i < teamCount; i++) { 762 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 763 if (barInfo->teams->HasItem((void*)(addr_t)team)) 764 return; 765 if (strcasecmp(barInfo->sig, sig) == 0) 766 multiLaunchTeam = barInfo; 767 } 768 769 if (multiLaunchTeam != NULL) { 770 multiLaunchTeam->teams->AddItem((void*)(addr_t)team); 771 772 int32 subsCount = sSubscribers.CountItems(); 773 if (subsCount > 0) { 774 BMessage message(kAddTeam); 775 message.AddInt32("team", team); 776 message.AddString("sig", multiLaunchTeam->sig); 777 778 for (int32 i = 0; i < subsCount; i++) 779 ((BMessenger*)sSubscribers.ItemAt(i))->SendMessage(&message); 780 } 781 return; 782 } 783 784 BFile file(ref, B_READ_ONLY); 785 BAppFileInfo appMime(&file); 786 787 BString name; 788 if (!gLocalizedNamePreferred 789 || BLocaleRoster::Default()->GetLocalizedFileName(name, *ref) 790 != B_OK) { 791 name = ref->name; 792 } 793 794 BarTeamInfo* barInfo = new BarTeamInfo(new BList(), flags, strdup(sig), 795 NULL, strdup(name.String())); 796 FetchAppIcon(barInfo); 797 barInfo->teams->AddItem((void*)(addr_t)team); 798 sBarTeamInfoList.AddItem(barInfo); 799 800 int32 subsCount = sSubscribers.CountItems(); 801 if (subsCount > 0) { 802 for (int32 i = 0; i < subsCount; i++) { 803 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 804 BMessage message(B_SOME_APP_LAUNCHED); 805 806 BList* tList = new BList(*(barInfo->teams)); 807 message.AddPointer("teams", tList); 808 809 BBitmap* icon = new BBitmap(barInfo->icon); 810 ASSERT(icon); 811 812 message.AddPointer("icon", icon); 813 814 message.AddInt32("flags", static_cast<int32>(barInfo->flags)); 815 message.AddString("name", barInfo->name); 816 message.AddString("sig", barInfo->sig); 817 818 messenger->SendMessage(&message); 819 } 820 } 821 } 822 823 824 void 825 TBarApp::RemoveTeam(team_id team) 826 { 827 BAutolock autolock(sSubscriberLock); 828 if (!autolock.IsLocked()) 829 return; 830 831 int32 teamCount = sBarTeamInfoList.CountItems(); 832 for (int32 i = 0; i < teamCount; i++) { 833 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 834 if (barInfo->teams->HasItem((void*)(addr_t)team)) { 835 int32 subsCount = sSubscribers.CountItems(); 836 if (subsCount > 0) { 837 BMessage message((barInfo->teams->CountItems() == 1) 838 ? B_SOME_APP_QUIT : kRemoveTeam); 839 840 message.AddInt32("team", team); 841 for (int32 i = 0; i < subsCount; i++) { 842 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 843 messenger->SendMessage(&message); 844 } 845 } 846 847 barInfo->teams->RemoveItem((void*)(addr_t)team); 848 if (barInfo->teams->CountItems() < 1) { 849 delete (BarTeamInfo*)sBarTeamInfoList.RemoveItem(i); 850 return; 851 } 852 } 853 } 854 } 855 856 857 void 858 TBarApp::ResizeTeamIcons() 859 { 860 for (int32 i = sBarTeamInfoList.CountItems() - 1; i >= 0; i--) { 861 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 862 if ((barInfo->flags & B_BACKGROUND_APP) == 0 863 && strcasecmp(barInfo->sig, kDeskbarSignature) != 0) { 864 FetchAppIcon(barInfo); 865 } 866 } 867 } 868 869 870 int32 871 TBarApp::IconSize() 872 { 873 return fSettings.iconSize; 874 } 875 876 877 void 878 TBarApp::ShowPreferencesWindow() 879 { 880 if (fPreferencesWindow == NULL) { 881 fPreferencesWindow = new PreferencesWindow(BRect(100, 100, 320, 240)); 882 fPreferencesWindow->Show(); 883 } else if (fPreferencesWindow->Lock()) { 884 if (fPreferencesWindow->IsHidden()) 885 fPreferencesWindow->Show(); 886 else 887 fPreferencesWindow->Activate(); 888 889 fPreferencesWindow->Unlock(); 890 } 891 } 892 893 894 void 895 TBarApp::QuitPreferencesWindow() 896 { 897 if (fPreferencesWindow == NULL) 898 return; 899 900 if (fPreferencesWindow->Lock()) { 901 fPreferencesWindow->Quit(); 902 // Quit() destroys the window so don't unlock 903 fPreferencesWindow = NULL; 904 } 905 } 906 907 908 void 909 TBarApp::FetchAppIcon(BarTeamInfo* barInfo) 910 { 911 int32 width = IconSize(); 912 int32 index = (width - kMinimumIconSize) / kIconSizeInterval; 913 914 // first look in the icon cache 915 barInfo->icon = barInfo->iconCache[index]; 916 if (barInfo->icon != NULL) 917 return; 918 919 // icon wasn't in cache, get it from be_roster and cache it 920 app_info appInfo; 921 icon_size size = width >= 31 ? B_LARGE_ICON : B_MINI_ICON; 922 BBitmap* icon = new BBitmap(IconRect(), kIconColorSpace); 923 if (be_roster->GetAppInfo(barInfo->sig, &appInfo) == B_OK) { 924 // fetch the app icon 925 BFile file(&appInfo.ref, B_READ_ONLY); 926 BAppFileInfo appMime(&file); 927 if (appMime.GetIcon(icon, size) == B_OK) { 928 delete barInfo->iconCache[index]; 929 barInfo->iconCache[index] = barInfo->icon = icon; 930 return; 931 } 932 } 933 934 // couldn't find the app icon 935 // fetch the generic 3 boxes icon and cache it 936 BMimeType defaultAppMime; 937 defaultAppMime.SetTo(B_APP_MIME_TYPE); 938 if (defaultAppMime.GetIcon(icon, size) == B_OK) { 939 delete barInfo->iconCache[index]; 940 barInfo->iconCache[index] = barInfo->icon = icon; 941 return; 942 } 943 944 // couldn't find generic 3 boxes icon 945 // fill with transparent 946 uint8* iconBits = (uint8*)icon->Bits(); 947 if (icon->ColorSpace() == B_RGBA32) { 948 int32 i = 0; 949 while (i < icon->BitsLength()) { 950 iconBits[i++] = B_TRANSPARENT_32_BIT.red; 951 iconBits[i++] = B_TRANSPARENT_32_BIT.green; 952 iconBits[i++] = B_TRANSPARENT_32_BIT.blue; 953 iconBits[i++] = B_TRANSPARENT_32_BIT.alpha; 954 } 955 } else { 956 // Assume B_CMAP8 957 for (int32 i = 0; i < icon->BitsLength(); i++) 958 iconBits[i] = B_TRANSPARENT_MAGIC_CMAP8; 959 } 960 961 delete barInfo->iconCache[index]; 962 barInfo->iconCache[index] = barInfo->icon = icon; 963 } 964 965 966 BRect 967 TBarApp::IconRect() 968 { 969 int32 iconSize = IconSize(); 970 return BRect(0, 0, iconSize - 1, iconSize - 1); 971 } 972 973 974 // #pragma mark - 975 976 977 BarTeamInfo::BarTeamInfo(BList* teams, uint32 flags, char* sig, BBitmap* icon, 978 char* name) 979 : 980 teams(teams), 981 flags(flags), 982 sig(sig), 983 icon(icon), 984 name(name) 985 { 986 _Init(); 987 } 988 989 990 BarTeamInfo::BarTeamInfo(const BarTeamInfo &info) 991 : 992 teams(new BList(*info.teams)), 993 flags(info.flags), 994 sig(strdup(info.sig)), 995 icon(new BBitmap(*info.icon)), 996 name(strdup(info.name)) 997 { 998 _Init(); 999 } 1000 1001 1002 BarTeamInfo::~BarTeamInfo() 1003 { 1004 delete teams; 1005 free(sig); 1006 free(name); 1007 for (int32 i = 0; i < kIconCacheCount; i++) 1008 delete iconCache[i]; 1009 } 1010 1011 1012 void 1013 BarTeamInfo::_Init() 1014 { 1015 for (int32 i = 0; i < kIconCacheCount; i++) 1016 iconCache[i] = NULL; 1017 } 1018