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 BServer(kDeskbarSignature, true, NULL), 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 B_LOCALE_CHANGED: 647 { 648 BLocaleRoster::Default()->Refresh(); 649 650 bool localize; 651 if (message->FindBool("filesys", &localize) == B_OK) 652 gLocalizedNamePreferred = localize; 653 } 654 // fall-through 655 656 case kShowHideTime: 657 case kShowSeconds: 658 case kShowDayOfWeek: 659 case kShowTimeZone: 660 case kGetClockSettings: 661 fStatusViewMessenger.SendMessage(message); 662 // Notify the replicant tray (through BarView) that the time 663 // interval has changed and it should update the time view 664 // and reflow the tray icons. 665 break; 666 667 default: 668 BApplication::MessageReceived(message); 669 break; 670 } 671 } 672 673 674 void 675 TBarApp::RefsReceived(BMessage* refs) 676 { 677 entry_ref ref; 678 for (int32 i = 0; refs->FindRef("refs", i, &ref) == B_OK; i++) { 679 BMessage refsReceived(B_REFS_RECEIVED); 680 refsReceived.AddRef("refs", &ref); 681 682 BEntry entry(&ref); 683 if (!entry.IsDirectory()) 684 TrackerLaunch(&refsReceived, false); 685 } 686 } 687 688 689 void 690 TBarApp::Subscribe(const BMessenger &subscriber, BList* list) 691 { 692 // called when ExpandoMenuBar, TeamMenu or Switcher are built/rebuilt 693 list->MakeEmpty(); 694 695 BAutolock autolock(sSubscriberLock); 696 if (!autolock.IsLocked()) 697 return; 698 699 int32 numTeams = sBarTeamInfoList.CountItems(); 700 for (int32 i = 0; i < numTeams; i++) { 701 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 702 BarTeamInfo* newBarInfo = new (std::nothrow) BarTeamInfo(*barInfo); 703 if (newBarInfo != NULL) 704 list->AddItem(newBarInfo); 705 } 706 707 int32 subsCount = sSubscribers.CountItems(); 708 for (int32 i = 0; i < subsCount; i++) { 709 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 710 if (*messenger == subscriber) 711 return; 712 } 713 714 sSubscribers.AddItem(new BMessenger(subscriber)); 715 } 716 717 718 void 719 TBarApp::Unsubscribe(const BMessenger &subscriber) 720 { 721 BAutolock autolock(sSubscriberLock); 722 if (!autolock.IsLocked()) 723 return; 724 725 int32 count = sSubscribers.CountItems(); 726 for (int32 i = 0; i < count; i++) { 727 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 728 if (*messenger == subscriber) { 729 sSubscribers.RemoveItem(i); 730 delete messenger; 731 break; 732 } 733 } 734 } 735 736 737 void 738 TBarApp::AddTeam(team_id team, uint32 flags, const char* sig, entry_ref* ref) 739 { 740 if ((flags & B_BACKGROUND_APP) != 0 741 || strcasecmp(sig, kDeskbarSignature) == 0) { 742 // don't add if a background app or Deskbar itself 743 return; 744 } 745 746 BAutolock autolock(sSubscriberLock); 747 if (!autolock.IsLocked()) 748 return; 749 750 // have we already seen this team, is this another instance of 751 // a known app? 752 BarTeamInfo* multiLaunchTeam = NULL; 753 int32 teamCount = sBarTeamInfoList.CountItems(); 754 for (int32 i = 0; i < teamCount; i++) { 755 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 756 if (barInfo->teams->HasItem((void*)(addr_t)team)) 757 return; 758 if (strcasecmp(barInfo->sig, sig) == 0) 759 multiLaunchTeam = barInfo; 760 } 761 762 if (multiLaunchTeam != NULL) { 763 multiLaunchTeam->teams->AddItem((void*)(addr_t)team); 764 765 int32 subsCount = sSubscribers.CountItems(); 766 if (subsCount > 0) { 767 BMessage message(kAddTeam); 768 message.AddInt32("team", team); 769 message.AddString("sig", multiLaunchTeam->sig); 770 771 for (int32 i = 0; i < subsCount; i++) 772 ((BMessenger*)sSubscribers.ItemAt(i))->SendMessage(&message); 773 } 774 return; 775 } 776 777 BFile file(ref, B_READ_ONLY); 778 BAppFileInfo appMime(&file); 779 780 BString name; 781 if (!gLocalizedNamePreferred 782 || BLocaleRoster::Default()->GetLocalizedFileName(name, *ref) 783 != B_OK) { 784 name = ref->name; 785 } 786 787 BarTeamInfo* barInfo = new BarTeamInfo(new BList(), flags, strdup(sig), 788 NULL, strdup(name.String())); 789 FetchAppIcon(barInfo); 790 barInfo->teams->AddItem((void*)(addr_t)team); 791 sBarTeamInfoList.AddItem(barInfo); 792 793 int32 subsCount = sSubscribers.CountItems(); 794 if (subsCount > 0) { 795 for (int32 i = 0; i < subsCount; i++) { 796 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 797 BMessage message(B_SOME_APP_LAUNCHED); 798 799 BList* tList = new BList(*(barInfo->teams)); 800 message.AddPointer("teams", tList); 801 802 BBitmap* icon = new BBitmap(barInfo->icon); 803 ASSERT(icon); 804 805 message.AddPointer("icon", icon); 806 807 message.AddInt32("flags", static_cast<int32>(barInfo->flags)); 808 message.AddString("name", barInfo->name); 809 message.AddString("sig", barInfo->sig); 810 811 messenger->SendMessage(&message); 812 } 813 } 814 } 815 816 817 void 818 TBarApp::RemoveTeam(team_id team) 819 { 820 BAutolock autolock(sSubscriberLock); 821 if (!autolock.IsLocked()) 822 return; 823 824 int32 teamCount = sBarTeamInfoList.CountItems(); 825 for (int32 i = 0; i < teamCount; i++) { 826 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 827 if (barInfo->teams->HasItem((void*)(addr_t)team)) { 828 int32 subsCount = sSubscribers.CountItems(); 829 if (subsCount > 0) { 830 BMessage message((barInfo->teams->CountItems() == 1) 831 ? B_SOME_APP_QUIT : kRemoveTeam); 832 833 message.AddInt32("team", team); 834 for (int32 i = 0; i < subsCount; i++) { 835 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 836 messenger->SendMessage(&message); 837 } 838 } 839 840 barInfo->teams->RemoveItem((void*)(addr_t)team); 841 if (barInfo->teams->CountItems() < 1) { 842 delete (BarTeamInfo*)sBarTeamInfoList.RemoveItem(i); 843 return; 844 } 845 } 846 } 847 } 848 849 850 void 851 TBarApp::ResizeTeamIcons() 852 { 853 for (int32 i = sBarTeamInfoList.CountItems() - 1; i >= 0; i--) { 854 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 855 if ((barInfo->flags & B_BACKGROUND_APP) == 0 856 && strcasecmp(barInfo->sig, kDeskbarSignature) != 0) { 857 FetchAppIcon(barInfo); 858 } 859 } 860 } 861 862 863 int32 864 TBarApp::IconSize() 865 { 866 return fSettings.iconSize; 867 } 868 869 870 void 871 TBarApp::ShowPreferencesWindow() 872 { 873 if (fPreferencesWindow == NULL) { 874 fPreferencesWindow = new PreferencesWindow(BRect(100, 100, 320, 240)); 875 fPreferencesWindow->Show(); 876 } else if (fPreferencesWindow->Lock()) { 877 if (fPreferencesWindow->IsHidden()) 878 fPreferencesWindow->Show(); 879 else 880 fPreferencesWindow->Activate(); 881 882 fPreferencesWindow->Unlock(); 883 } 884 } 885 886 887 void 888 TBarApp::QuitPreferencesWindow() 889 { 890 if (fPreferencesWindow == NULL) 891 return; 892 893 if (fPreferencesWindow->Lock()) { 894 fPreferencesWindow->Quit(); 895 // Quit() destroys the window so don't unlock 896 fPreferencesWindow = NULL; 897 } 898 } 899 900 901 void 902 TBarApp::FetchAppIcon(BarTeamInfo* barInfo) 903 { 904 int32 width = IconSize(); 905 int32 index = (width - kMinimumIconSize) / kIconSizeInterval; 906 907 // first look in the icon cache 908 barInfo->icon = barInfo->iconCache[index]; 909 if (barInfo->icon != NULL) 910 return; 911 912 // icon wasn't in cache, get it from be_roster and cache it 913 app_info appInfo; 914 icon_size size = width >= 31 ? B_LARGE_ICON : B_MINI_ICON; 915 BBitmap* icon = new BBitmap(IconRect(), kIconColorSpace); 916 if (be_roster->GetAppInfo(barInfo->sig, &appInfo) == B_OK) { 917 // fetch the app icon 918 BFile file(&appInfo.ref, B_READ_ONLY); 919 BAppFileInfo appMime(&file); 920 if (appMime.GetIcon(icon, size) == B_OK) { 921 delete barInfo->iconCache[index]; 922 barInfo->iconCache[index] = barInfo->icon = icon; 923 return; 924 } 925 } 926 927 // couldn't find the app icon 928 // fetch the generic 3 boxes icon and cache it 929 BMimeType defaultAppMime; 930 defaultAppMime.SetTo(B_APP_MIME_TYPE); 931 if (defaultAppMime.GetIcon(icon, size) == B_OK) { 932 delete barInfo->iconCache[index]; 933 barInfo->iconCache[index] = barInfo->icon = icon; 934 return; 935 } 936 937 // couldn't find generic 3 boxes icon 938 // fill with transparent 939 uint8* iconBits = (uint8*)icon->Bits(); 940 if (icon->ColorSpace() == B_RGBA32) { 941 int32 i = 0; 942 while (i < icon->BitsLength()) { 943 iconBits[i++] = B_TRANSPARENT_32_BIT.red; 944 iconBits[i++] = B_TRANSPARENT_32_BIT.green; 945 iconBits[i++] = B_TRANSPARENT_32_BIT.blue; 946 iconBits[i++] = B_TRANSPARENT_32_BIT.alpha; 947 } 948 } else { 949 // Assume B_CMAP8 950 for (int32 i = 0; i < icon->BitsLength(); i++) 951 iconBits[i] = B_TRANSPARENT_MAGIC_CMAP8; 952 } 953 954 delete barInfo->iconCache[index]; 955 barInfo->iconCache[index] = barInfo->icon = icon; 956 } 957 958 959 BRect 960 TBarApp::IconRect() 961 { 962 int32 iconSize = IconSize(); 963 return BRect(0, 0, iconSize - 1, iconSize - 1); 964 } 965 966 967 // #pragma mark - 968 969 970 BarTeamInfo::BarTeamInfo(BList* teams, uint32 flags, char* sig, BBitmap* icon, 971 char* name) 972 : 973 teams(teams), 974 flags(flags), 975 sig(sig), 976 icon(icon), 977 name(name) 978 { 979 _Init(); 980 } 981 982 983 BarTeamInfo::BarTeamInfo(const BarTeamInfo &info) 984 : 985 teams(new BList(*info.teams)), 986 flags(info.flags), 987 sig(strdup(info.sig)), 988 icon(new BBitmap(*info.icon)), 989 name(strdup(info.name)) 990 { 991 _Init(); 992 } 993 994 995 BarTeamInfo::~BarTeamInfo() 996 { 997 delete teams; 998 free(sig); 999 free(name); 1000 for (int32 i = 0; i < kIconCacheCount; i++) 1001 delete iconCache[i]; 1002 } 1003 1004 1005 void 1006 BarTeamInfo::_Init() 1007 { 1008 for (int32 i = 0; i < kIconCacheCount; i++) 1009 iconCache[i] = NULL; 1010 } 1011