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