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