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 = gMinimumWindowWidth; 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 // constrain width setting within limits 338 if (settings.width < gMinimumWindowWidth) 339 settings.width = gMinimumWindowWidth; 340 else if (settings.width > gMaximumWindowWidth) 341 settings.width = gMaximumWindowWidth; 342 343 filePath = dirPath; 344 filePath.Append(clockSettingsFileName); 345 fClockSettingsFile = new BFile(filePath.Path(), O_RDWR); 346 if (fClockSettingsFile->InitCheck() != B_OK) { 347 BDirectory theDir(dirPath.Path()); 348 if (theDir.InitCheck() == B_OK) 349 theDir.CreateFile(clockSettingsFileName, fClockSettingsFile); 350 } 351 352 if (fClockSettingsFile->InitCheck() == B_OK 353 && prefs.Unflatten(fClockSettingsFile) == B_OK) { 354 clock.showSeconds = prefs.GetBool("showSeconds", false); 355 clock.showDayOfWeek = prefs.GetBool("showDayOfWeek", false); 356 clock.showTimeZone = prefs.GetBool("showTimeZone", false); 357 } 358 } 359 360 fSettings = settings; 361 fClockSettings = clock; 362 } 363 364 365 void 366 TBarApp::MessageReceived(BMessage* message) 367 { 368 switch (message->what) { 369 case 'gloc': 370 case 'sloc': 371 case 'gexp': 372 case 'sexp': 373 case 'info': 374 case 'exst': 375 case 'cwnt': 376 case 'icon': 377 case 'remv': 378 case 'adon': 379 // pass any BDeskbar originating messages on to the window 380 fBarWindow->PostMessage(message); 381 break; 382 383 case kConfigShow: 384 ShowPreferencesWindow(); 385 break; 386 387 case kConfigQuit: 388 QuitPreferencesWindow(); 389 break; 390 391 case kStateChanged: 392 if (fPreferencesWindow != NULL) 393 fPreferencesWindow->PostMessage(kStateChanged); 394 break; 395 396 case kShowDeskbarMenu: 397 if (fBarWindow->Lock()) { 398 fBarWindow->ShowDeskbarMenu(); 399 fBarWindow->Unlock(); 400 } 401 break; 402 403 case kShowTeamMenu: 404 if (fBarWindow->Lock()) { 405 fBarWindow->ShowTeamMenu(); 406 fBarWindow->Unlock(); 407 } 408 break; 409 410 case kUpdateRecentCounts: 411 int32 count; 412 bool enabled; 413 414 if (message->FindInt32("applications", &count) == B_OK) 415 fSettings.recentAppsCount = count; 416 if (message->FindBool("applicationsEnabled", &enabled) == B_OK) 417 fSettings.recentAppsEnabled = enabled && count > 0; 418 419 if (message->FindInt32("folders", &count) == B_OK) 420 fSettings.recentFoldersCount = count; 421 if (message->FindBool("foldersEnabled", &enabled) == B_OK) 422 fSettings.recentFoldersEnabled = enabled && count > 0; 423 424 if (message->FindInt32("documents", &count) == B_OK) 425 fSettings.recentDocsCount = count; 426 if (message->FindBool("documentsEnabled", &enabled) == B_OK) 427 fSettings.recentDocsEnabled = enabled && count > 0; 428 429 if (fPreferencesWindow != NULL) 430 fPreferencesWindow->PostMessage(kUpdatePreferences); 431 break; 432 433 case B_SOME_APP_LAUNCHED: 434 { 435 team_id team = -1; 436 message->FindInt32("be:team", &team); 437 438 uint32 flags = 0; 439 message->FindInt32("be:flags", (int32*)&flags); 440 441 const char* signature = NULL; 442 message->FindString("be:signature", &signature); 443 444 entry_ref ref; 445 message->FindRef("be:ref", &ref); 446 447 AddTeam(team, flags, signature, &ref); 448 break; 449 } 450 451 case B_SOME_APP_QUIT: 452 { 453 team_id team = -1; 454 message->FindInt32("be:team", &team); 455 RemoveTeam(team); 456 break; 457 } 458 459 case B_ARCHIVED_OBJECT: 460 // TODO: what's this??? 461 message->AddString("special", "Alex Osadzinski"); 462 fStatusViewMessenger.SendMessage(message); 463 break; 464 465 case kToggleDraggers: 466 if (BDragger::AreDraggersDrawn()) 467 BDragger::HideAllDraggers(); 468 else 469 BDragger::ShowAllDraggers(); 470 break; 471 472 case kAlwaysTop: 473 fSettings.alwaysOnTop = !fSettings.alwaysOnTop; 474 475 if (fPreferencesWindow != NULL) 476 fPreferencesWindow->PostMessage(kUpdatePreferences); 477 478 fBarWindow->SetFeel(fSettings.alwaysOnTop 479 ? B_FLOATING_ALL_WINDOW_FEEL 480 : B_NORMAL_WINDOW_FEEL); 481 break; 482 483 case kAutoRaise: 484 fSettings.autoRaise = fSettings.alwaysOnTop ? false 485 : !fSettings.autoRaise; 486 487 if (fPreferencesWindow != NULL) 488 fPreferencesWindow->PostMessage(kUpdatePreferences); 489 break; 490 491 case kAutoHide: 492 fSettings.autoHide = !fSettings.autoHide; 493 494 if (fPreferencesWindow != NULL) 495 fPreferencesWindow->PostMessage(kUpdatePreferences); 496 497 fBarWindow->Lock(); 498 fBarView->HideDeskbar(fSettings.autoHide); 499 fBarWindow->Unlock(); 500 break; 501 502 case kTrackerFirst: 503 fSettings.trackerAlwaysFirst = !fSettings.trackerAlwaysFirst; 504 505 if (fPreferencesWindow != NULL) 506 fPreferencesWindow->PostMessage(kUpdatePreferences); 507 508 // if mini mode we don't need to update the view 509 if (fBarView->MiniState()) 510 break; 511 512 fBarWindow->Lock(); 513 fBarView->PlaceApplicationBar(); 514 fBarWindow->Unlock(); 515 break; 516 517 case kSortRunningApps: 518 fSettings.sortRunningApps = !fSettings.sortRunningApps; 519 520 if (fPreferencesWindow != NULL) 521 fPreferencesWindow->PostMessage(kUpdatePreferences); 522 523 // if mini mode we don't need to update the view 524 if (fBarView->MiniState()) 525 break; 526 527 fBarWindow->Lock(); 528 fBarView->PlaceApplicationBar(); 529 fBarWindow->Unlock(); 530 break; 531 532 case kUnsubscribe: 533 { 534 BMessenger messenger; 535 if (message->FindMessenger("messenger", &messenger) == B_OK) 536 Unsubscribe(messenger); 537 break; 538 } 539 540 case kSuperExpando: 541 fSettings.superExpando = !fSettings.superExpando; 542 543 if (fPreferencesWindow != NULL) 544 fPreferencesWindow->PostMessage(kUpdatePreferences); 545 546 // if mini mode we don't need to update the view 547 if (fBarView->MiniState()) 548 break; 549 550 fBarWindow->Lock(); 551 fBarView->PlaceApplicationBar(); 552 fBarWindow->Unlock(); 553 break; 554 555 case kExpandNewTeams: 556 fSettings.expandNewTeams = !fSettings.expandNewTeams; 557 558 if (fPreferencesWindow != NULL) 559 fPreferencesWindow->PostMessage(kUpdatePreferences); 560 561 // if mini mode we don't need to update the view 562 if (fBarView->MiniState()) 563 break; 564 565 fBarWindow->Lock(); 566 fBarView->PlaceApplicationBar(); 567 fBarWindow->Unlock(); 568 break; 569 570 case kHideLabels: 571 fSettings.hideLabels = !fSettings.hideLabels; 572 573 if (fPreferencesWindow != NULL) 574 fPreferencesWindow->PostMessage(kUpdatePreferences); 575 576 // if mini mode we don't need to update the view 577 if (fBarView->MiniState()) 578 break; 579 580 fBarWindow->Lock(); 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 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 B_LOCALE_CHANGED: 654 { 655 BLocaleRoster::Default()->Refresh(); 656 657 bool localize; 658 if (message->FindBool("filesys", &localize) == B_OK) 659 gLocalizedNamePreferred = localize; 660 } 661 // fall-through 662 663 case kRealignReplicants: 664 case kShowHideTime: 665 case kShowSeconds: 666 case kShowDayOfWeek: 667 case kShowTimeZone: 668 case kGetClockSettings: 669 fStatusViewMessenger.SendMessage(message); 670 // Notify the replicant tray (through BarView) that the time 671 // interval has changed and it should update the time view 672 // and reflow the tray icons. 673 break; 674 675 default: 676 BApplication::MessageReceived(message); 677 break; 678 } 679 } 680 681 682 void 683 TBarApp::RefsReceived(BMessage* refs) 684 { 685 entry_ref ref; 686 for (int32 i = 0; refs->FindRef("refs", i, &ref) == B_OK; i++) { 687 BMessage refsReceived(B_REFS_RECEIVED); 688 refsReceived.AddRef("refs", &ref); 689 690 BEntry entry(&ref); 691 if (!entry.IsDirectory()) 692 TrackerLaunch(&refsReceived, false); 693 } 694 } 695 696 697 void 698 TBarApp::Subscribe(const BMessenger &subscriber, BList* list) 699 { 700 // called when ExpandoMenuBar, TeamMenu or Switcher are built/rebuilt 701 list->MakeEmpty(); 702 703 BAutolock autolock(sSubscriberLock); 704 if (!autolock.IsLocked()) 705 return; 706 707 int32 numTeams = sBarTeamInfoList.CountItems(); 708 for (int32 i = 0; i < numTeams; i++) { 709 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 710 BarTeamInfo* newBarInfo = new (std::nothrow) BarTeamInfo(*barInfo); 711 if (newBarInfo != NULL) 712 list->AddItem(newBarInfo); 713 } 714 715 int32 subsCount = sSubscribers.CountItems(); 716 for (int32 i = 0; i < subsCount; i++) { 717 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 718 if (*messenger == subscriber) 719 return; 720 } 721 722 sSubscribers.AddItem(new BMessenger(subscriber)); 723 } 724 725 726 void 727 TBarApp::Unsubscribe(const BMessenger &subscriber) 728 { 729 BAutolock autolock(sSubscriberLock); 730 if (!autolock.IsLocked()) 731 return; 732 733 int32 count = sSubscribers.CountItems(); 734 for (int32 i = 0; i < count; i++) { 735 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 736 if (*messenger == subscriber) { 737 sSubscribers.RemoveItem(i); 738 delete messenger; 739 break; 740 } 741 } 742 } 743 744 745 void 746 TBarApp::AddTeam(team_id team, uint32 flags, const char* sig, entry_ref* ref) 747 { 748 if ((flags & B_BACKGROUND_APP) != 0 749 || strcasecmp(sig, kDeskbarSignature) == 0) { 750 // don't add if a background app or Deskbar itself 751 return; 752 } 753 754 BAutolock autolock(sSubscriberLock); 755 if (!autolock.IsLocked()) 756 return; 757 758 // have we already seen this team, is this another instance of 759 // a known app? 760 BarTeamInfo* multiLaunchTeam = NULL; 761 int32 teamCount = sBarTeamInfoList.CountItems(); 762 for (int32 i = 0; i < teamCount; i++) { 763 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 764 if (barInfo->teams->HasItem((void*)(addr_t)team)) 765 return; 766 if (strcasecmp(barInfo->sig, sig) == 0) 767 multiLaunchTeam = barInfo; 768 } 769 770 if (multiLaunchTeam != NULL) { 771 multiLaunchTeam->teams->AddItem((void*)(addr_t)team); 772 773 int32 subsCount = sSubscribers.CountItems(); 774 if (subsCount > 0) { 775 BMessage message(kAddTeam); 776 message.AddInt32("team", team); 777 message.AddString("sig", multiLaunchTeam->sig); 778 779 for (int32 i = 0; i < subsCount; i++) 780 ((BMessenger*)sSubscribers.ItemAt(i))->SendMessage(&message); 781 } 782 return; 783 } 784 785 BFile file(ref, B_READ_ONLY); 786 BAppFileInfo appMime(&file); 787 788 BString name; 789 if (!gLocalizedNamePreferred 790 || BLocaleRoster::Default()->GetLocalizedFileName(name, *ref) 791 != B_OK) { 792 name = ref->name; 793 } 794 795 BarTeamInfo* barInfo = new BarTeamInfo(new BList(), flags, strdup(sig), 796 NULL, strdup(name.String())); 797 FetchAppIcon(barInfo); 798 barInfo->teams->AddItem((void*)(addr_t)team); 799 sBarTeamInfoList.AddItem(barInfo); 800 801 int32 subsCount = sSubscribers.CountItems(); 802 if (subsCount > 0) { 803 for (int32 i = 0; i < subsCount; i++) { 804 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 805 BMessage message(B_SOME_APP_LAUNCHED); 806 807 BList* tList = new BList(*(barInfo->teams)); 808 message.AddPointer("teams", tList); 809 810 BBitmap* icon = new BBitmap(barInfo->icon); 811 ASSERT(icon); 812 813 message.AddPointer("icon", icon); 814 815 message.AddInt32("flags", static_cast<int32>(barInfo->flags)); 816 message.AddString("name", barInfo->name); 817 message.AddString("sig", barInfo->sig); 818 819 messenger->SendMessage(&message); 820 } 821 } 822 } 823 824 825 void 826 TBarApp::RemoveTeam(team_id team) 827 { 828 BAutolock autolock(sSubscriberLock); 829 if (!autolock.IsLocked()) 830 return; 831 832 int32 teamCount = sBarTeamInfoList.CountItems(); 833 for (int32 i = 0; i < teamCount; i++) { 834 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 835 if (barInfo->teams->HasItem((void*)(addr_t)team)) { 836 int32 subsCount = sSubscribers.CountItems(); 837 if (subsCount > 0) { 838 BMessage message((barInfo->teams->CountItems() == 1) 839 ? B_SOME_APP_QUIT : kRemoveTeam); 840 841 message.AddInt32("team", team); 842 for (int32 i = 0; i < subsCount; i++) { 843 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 844 messenger->SendMessage(&message); 845 } 846 } 847 848 barInfo->teams->RemoveItem((void*)(addr_t)team); 849 if (barInfo->teams->CountItems() < 1) { 850 delete (BarTeamInfo*)sBarTeamInfoList.RemoveItem(i); 851 return; 852 } 853 } 854 } 855 } 856 857 858 void 859 TBarApp::ResizeTeamIcons() 860 { 861 for (int32 i = sBarTeamInfoList.CountItems() - 1; i >= 0; i--) { 862 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 863 if ((barInfo->flags & B_BACKGROUND_APP) == 0 864 && strcasecmp(barInfo->sig, kDeskbarSignature) != 0) { 865 FetchAppIcon(barInfo); 866 } 867 } 868 } 869 870 871 int32 872 TBarApp::IconSize() 873 { 874 return fSettings.iconSize; 875 } 876 877 878 void 879 TBarApp::ShowPreferencesWindow() 880 { 881 if (fPreferencesWindow == NULL) { 882 fPreferencesWindow = new PreferencesWindow(BRect(100, 100, 320, 240)); 883 fPreferencesWindow->Show(); 884 } else if (fPreferencesWindow->Lock()) { 885 if (fPreferencesWindow->IsHidden()) 886 fPreferencesWindow->Show(); 887 else 888 fPreferencesWindow->Activate(); 889 890 fPreferencesWindow->Unlock(); 891 } 892 } 893 894 895 void 896 TBarApp::QuitPreferencesWindow() 897 { 898 if (fPreferencesWindow == NULL) 899 return; 900 901 if (fPreferencesWindow->Lock()) { 902 fPreferencesWindow->Quit(); 903 // Quit() destroys the window so don't unlock 904 fPreferencesWindow = NULL; 905 } 906 } 907 908 909 void 910 TBarApp::FetchAppIcon(BarTeamInfo* barInfo) 911 { 912 int32 width = IconSize(); 913 int32 index = (width - kMinimumIconSize) / kIconSizeInterval; 914 915 // first look in the icon cache 916 barInfo->icon = barInfo->iconCache[index]; 917 if (barInfo->icon != NULL) 918 return; 919 920 // icon wasn't in cache, get it from be_roster and cache it 921 app_info appInfo; 922 icon_size size = width >= 31 ? B_LARGE_ICON : B_MINI_ICON; 923 BBitmap* icon = new BBitmap(IconRect(), kIconColorSpace); 924 if (be_roster->GetAppInfo(barInfo->sig, &appInfo) == B_OK) { 925 // fetch the app icon 926 BFile file(&appInfo.ref, B_READ_ONLY); 927 BAppFileInfo appMime(&file); 928 if (appMime.GetIcon(icon, size) == B_OK) { 929 delete barInfo->iconCache[index]; 930 barInfo->iconCache[index] = barInfo->icon = icon; 931 return; 932 } 933 } 934 935 // couldn't find the app icon 936 // fetch the generic 3 boxes icon and cache it 937 BMimeType defaultAppMime; 938 defaultAppMime.SetTo(B_APP_MIME_TYPE); 939 if (defaultAppMime.GetIcon(icon, size) == B_OK) { 940 delete barInfo->iconCache[index]; 941 barInfo->iconCache[index] = barInfo->icon = icon; 942 return; 943 } 944 945 // couldn't find generic 3 boxes icon 946 // fill with transparent 947 uint8* iconBits = (uint8*)icon->Bits(); 948 if (icon->ColorSpace() == B_RGBA32) { 949 int32 i = 0; 950 while (i < icon->BitsLength()) { 951 iconBits[i++] = B_TRANSPARENT_32_BIT.red; 952 iconBits[i++] = B_TRANSPARENT_32_BIT.green; 953 iconBits[i++] = B_TRANSPARENT_32_BIT.blue; 954 iconBits[i++] = B_TRANSPARENT_32_BIT.alpha; 955 } 956 } else { 957 // Assume B_CMAP8 958 for (int32 i = 0; i < icon->BitsLength(); i++) 959 iconBits[i] = B_TRANSPARENT_MAGIC_CMAP8; 960 } 961 962 delete barInfo->iconCache[index]; 963 barInfo->iconCache[index] = barInfo->icon = icon; 964 } 965 966 967 BRect 968 TBarApp::IconRect() 969 { 970 int32 iconSize = IconSize(); 971 return BRect(0, 0, iconSize - 1, iconSize - 1); 972 } 973 974 975 // #pragma mark - 976 977 978 BarTeamInfo::BarTeamInfo(BList* teams, uint32 flags, char* sig, BBitmap* icon, 979 char* name) 980 : 981 teams(teams), 982 flags(flags), 983 sig(sig), 984 icon(icon), 985 name(name) 986 { 987 _Init(); 988 } 989 990 991 BarTeamInfo::BarTeamInfo(const BarTeamInfo &info) 992 : 993 teams(new BList(*info.teams)), 994 flags(info.flags), 995 sig(strdup(info.sig)), 996 icon(new BBitmap(*info.icon)), 997 name(strdup(info.name)) 998 { 999 _Init(); 1000 } 1001 1002 1003 BarTeamInfo::~BarTeamInfo() 1004 { 1005 delete teams; 1006 free(sig); 1007 free(name); 1008 for (int32 i = 0; i < kIconCacheCount; i++) 1009 delete iconCache[i]; 1010 } 1011 1012 1013 void 1014 BarTeamInfo::_Init() 1015 { 1016 for (int32 i = 0; i < kIconCacheCount; i++) 1017 iconCache[i] = NULL; 1018 } 1019