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