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 58 #include <DeskbarPrivate.h> 59 #include <RosterPrivate.h> 60 #include "tracker_private.h" 61 62 #include "BarView.h" 63 #include "BarWindow.h" 64 #include "DeskbarUtils.h" 65 #include "FSUtils.h" 66 #include "PreferencesWindow.h" 67 #include "ResourceSet.h" 68 #include "StatusView.h" 69 #include "Switcher.h" 70 #include "Utilities.h" 71 72 #include "icons.h" 73 74 75 BLocker TBarApp::sSubscriberLock; 76 BList TBarApp::sBarTeamInfoList; 77 BList TBarApp::sSubscribers; 78 79 80 const uint32 kShowDeskbarMenu = 'BeMn'; 81 const uint32 kShowTeamMenu = 'TmMn'; 82 83 static const color_space kIconColorSpace = B_RGBA32; 84 85 86 int 87 main() 88 { 89 setlocale(LC_ALL, ""); 90 TBarApp app; 91 app.Run(); 92 93 return B_OK; 94 } 95 96 97 TBarApp::TBarApp() 98 : 99 BServer(kDeskbarSignature, true, NULL), 100 fSettingsFile(NULL), 101 fClockSettingsFile(NULL), 102 fPreferencesWindow(NULL) 103 { 104 InitSettings(); 105 InitIconPreloader(); 106 107 fBarWindow = new TBarWindow(); 108 fBarView = fBarWindow->BarView(); 109 110 be_roster->StartWatching(this); 111 112 gLocalizedNamePreferred 113 = BLocaleRoster::Default()->IsFilesystemTranslationPreferred(); 114 115 sBarTeamInfoList.MakeEmpty(); 116 117 BList teamList; 118 int32 numTeams; 119 be_roster->GetAppList(&teamList); 120 numTeams = teamList.CountItems(); 121 for (int32 i = 0; i < numTeams; i++) { 122 app_info appInfo; 123 team_id tID = (addr_t)teamList.ItemAt(i); 124 if (be_roster->GetRunningAppInfo(tID, &appInfo) == B_OK) { 125 AddTeam(appInfo.team, appInfo.flags, appInfo.signature, 126 &appInfo.ref); 127 } 128 } 129 130 sSubscribers.MakeEmpty(); 131 fSwitcherMessenger = BMessenger(new TSwitchManager(fSettings.switcherLoc)); 132 fBarWindow->Show(); 133 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 = gMinimumWindowWidth; 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 // constrain width setting within limits 340 if (settings.width < gMinimumWindowWidth) 341 settings.width = gMinimumWindowWidth; 342 else if (settings.width > gMaximumWindowWidth) 343 settings.width = gMaximumWindowWidth; 344 345 filePath = dirPath; 346 filePath.Append(clockSettingsFileName); 347 fClockSettingsFile = new BFile(filePath.Path(), O_RDWR); 348 if (fClockSettingsFile->InitCheck() != B_OK) { 349 BDirectory theDir(dirPath.Path()); 350 if (theDir.InitCheck() == B_OK) 351 theDir.CreateFile(clockSettingsFileName, fClockSettingsFile); 352 } 353 354 if (fClockSettingsFile->InitCheck() == B_OK 355 && prefs.Unflatten(fClockSettingsFile) == B_OK) { 356 clock.showSeconds = prefs.GetBool("showSeconds", false); 357 clock.showDayOfWeek = prefs.GetBool("showDayOfWeek", false); 358 clock.showTimeZone = prefs.GetBool("showTimeZone", false); 359 } 360 } 361 362 fSettings = settings; 363 fClockSettings = clock; 364 } 365 366 367 void 368 TBarApp::MessageReceived(BMessage* message) 369 { 370 switch (message->what) { 371 // BDeskbar originating messages we can handle 372 case kMsgIsAlwaysOnTop: 373 { 374 BMessage reply('rply'); 375 reply.AddBool("always on top", fSettings.alwaysOnTop); 376 message->SendReply(&reply); 377 break; 378 } 379 case kMsgIsAutoRaise: 380 { 381 BMessage reply('rply'); 382 reply.AddBool("auto raise", fSettings.autoRaise); 383 message->SendReply(&reply); 384 break; 385 } 386 case kMsgIsAutoHide: 387 { 388 BMessage reply('rply'); 389 reply.AddBool("auto hide", fSettings.autoHide); 390 message->SendReply(&reply); 391 break; 392 } 393 394 // pass rest of BDeskbar originating messages onto the window 395 // (except for setters handled below) 396 case kMsgLocation: 397 case kMsgSetLocation: 398 case kMsgIsExpanded: 399 case kMsgExpand: 400 case kMsgGetItemInfo: 401 case kMsgHasItem: 402 case kMsgCountItems: 403 case kMsgMaxItemSize: 404 case kMsgAddView: 405 case kMsgRemoveItem: 406 case kMsgAddAddOn: 407 fBarWindow->PostMessage(message); 408 break; 409 410 case kConfigShow: 411 ShowPreferencesWindow(); 412 break; 413 414 case kConfigQuit: 415 QuitPreferencesWindow(); 416 break; 417 418 case kStateChanged: 419 if (fPreferencesWindow != NULL) 420 fPreferencesWindow->PostMessage(kStateChanged); 421 break; 422 423 case kShowDeskbarMenu: 424 if (fBarWindow->Lock()) { 425 fBarWindow->ShowDeskbarMenu(); 426 fBarWindow->Unlock(); 427 } 428 break; 429 430 case kShowTeamMenu: 431 if (fBarWindow->Lock()) { 432 fBarWindow->ShowTeamMenu(); 433 fBarWindow->Unlock(); 434 } 435 break; 436 437 case kUpdateRecentCounts: 438 int32 count; 439 bool enabled; 440 441 if (message->FindInt32("applications", &count) == B_OK) 442 fSettings.recentAppsCount = count; 443 if (message->FindBool("applicationsEnabled", &enabled) == B_OK) 444 fSettings.recentAppsEnabled = enabled && count > 0; 445 446 if (message->FindInt32("folders", &count) == B_OK) 447 fSettings.recentFoldersCount = count; 448 if (message->FindBool("foldersEnabled", &enabled) == B_OK) 449 fSettings.recentFoldersEnabled = enabled && count > 0; 450 451 if (message->FindInt32("documents", &count) == B_OK) 452 fSettings.recentDocsCount = count; 453 if (message->FindBool("documentsEnabled", &enabled) == B_OK) 454 fSettings.recentDocsEnabled = enabled && count > 0; 455 456 if (fPreferencesWindow != NULL) 457 fPreferencesWindow->PostMessage(kUpdatePreferences); 458 break; 459 460 case B_SOME_APP_LAUNCHED: 461 { 462 team_id team = -1; 463 message->FindInt32("be:team", &team); 464 465 uint32 flags = 0; 466 message->FindInt32("be:flags", (int32*)&flags); 467 468 const char* signature = NULL; 469 message->FindString("be:signature", &signature); 470 471 entry_ref ref; 472 message->FindRef("be:ref", &ref); 473 474 AddTeam(team, flags, signature, &ref); 475 break; 476 } 477 478 case B_SOME_APP_QUIT: 479 { 480 team_id team = -1; 481 message->FindInt32("be:team", &team); 482 RemoveTeam(team); 483 break; 484 } 485 486 case B_ARCHIVED_OBJECT: 487 // TODO: what's this??? 488 message->AddString("special", "Alex Osadzinski"); 489 fStatusViewMessenger.SendMessage(message); 490 break; 491 492 case kToggleDraggers: 493 if (BDragger::AreDraggersDrawn()) 494 BDragger::HideAllDraggers(); 495 else 496 BDragger::ShowAllDraggers(); 497 break; 498 499 case kMsgAlwaysOnTop: // from BDeskbar 500 case kAlwaysTop: 501 fSettings.alwaysOnTop = !fSettings.alwaysOnTop; 502 503 if (fPreferencesWindow != NULL) 504 fPreferencesWindow->PostMessage(kUpdatePreferences); 505 506 fBarWindow->SetFeel(fSettings.alwaysOnTop 507 ? B_FLOATING_ALL_WINDOW_FEEL 508 : B_NORMAL_WINDOW_FEEL); 509 break; 510 511 case kMsgAutoRaise: // from BDeskbar 512 case kAutoRaise: 513 fSettings.autoRaise = fSettings.alwaysOnTop ? false 514 : !fSettings.autoRaise; 515 516 if (fPreferencesWindow != NULL) 517 fPreferencesWindow->PostMessage(kUpdatePreferences); 518 break; 519 520 case kMsgAutoHide: // from BDeskbar 521 case kAutoHide: 522 fSettings.autoHide = !fSettings.autoHide; 523 524 if (fPreferencesWindow != NULL) 525 fPreferencesWindow->PostMessage(kUpdatePreferences); 526 527 fBarWindow->Lock(); 528 fBarView->HideDeskbar(fSettings.autoHide); 529 fBarWindow->Unlock(); 530 break; 531 532 case kTrackerFirst: 533 fSettings.trackerAlwaysFirst = !fSettings.trackerAlwaysFirst; 534 535 if (fPreferencesWindow != NULL) 536 fPreferencesWindow->PostMessage(kUpdatePreferences); 537 538 // if mini mode we don't need to update the view 539 if (fBarView->MiniState()) 540 break; 541 542 fBarWindow->Lock(); 543 fBarView->PlaceApplicationBar(); 544 fBarWindow->Unlock(); 545 break; 546 547 case kSortRunningApps: 548 fSettings.sortRunningApps = !fSettings.sortRunningApps; 549 550 if (fPreferencesWindow != NULL) 551 fPreferencesWindow->PostMessage(kUpdatePreferences); 552 553 // if mini mode we don't need to update the view 554 if (fBarView->MiniState()) 555 break; 556 557 fBarWindow->Lock(); 558 fBarView->PlaceApplicationBar(); 559 fBarWindow->Unlock(); 560 break; 561 562 case kUnsubscribe: 563 { 564 BMessenger messenger; 565 if (message->FindMessenger("messenger", &messenger) == B_OK) 566 Unsubscribe(messenger); 567 break; 568 } 569 570 case kSuperExpando: 571 fSettings.superExpando = !fSettings.superExpando; 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 kExpandNewTeams: 586 fSettings.expandNewTeams = !fSettings.expandNewTeams; 587 588 if (fPreferencesWindow != NULL) 589 fPreferencesWindow->PostMessage(kUpdatePreferences); 590 591 // if mini mode we don't need to update the view 592 if (fBarView->MiniState()) 593 break; 594 595 fBarWindow->Lock(); 596 fBarView->PlaceApplicationBar(); 597 fBarWindow->Unlock(); 598 break; 599 600 case kHideLabels: 601 fSettings.hideLabels = !fSettings.hideLabels; 602 603 if (fPreferencesWindow != NULL) 604 fPreferencesWindow->PostMessage(kUpdatePreferences); 605 606 // if mini mode we don't need to update the view 607 if (fBarView->MiniState()) 608 break; 609 610 fBarWindow->Lock(); 611 fBarView->PlaceApplicationBar(); 612 fBarWindow->Unlock(); 613 break; 614 615 case kResizeTeamIcons: 616 { 617 int32 oldIconSize = fSettings.iconSize; 618 int32 iconSize; 619 if (message->FindInt32("be:value", &iconSize) != B_OK) 620 break; 621 622 fSettings.iconSize = iconSize * kIconSizeInterval; 623 624 // pin icon size between min and max values 625 if (fSettings.iconSize < kMinimumIconSize) 626 fSettings.iconSize = kMinimumIconSize; 627 else if (fSettings.iconSize > kMaximumIconSize) 628 fSettings.iconSize = kMaximumIconSize; 629 630 // don't resize if icon size hasn't changed 631 if (fSettings.iconSize == oldIconSize) 632 break; 633 634 ResizeTeamIcons(); 635 636 if (fPreferencesWindow != NULL) 637 fPreferencesWindow->PostMessage(kUpdatePreferences); 638 639 // if mini mode we don't need to update the view 640 if (fBarView->MiniState()) 641 break; 642 643 fBarWindow->Lock(); 644 if (!fBarView->Vertical()) { 645 // Must also resize the Deskbar menu and replicant tray in 646 // horizontal mode 647 fBarView->PlaceDeskbarMenu(); 648 fBarView->PlaceTray(false, false); 649 } 650 fBarView->PlaceApplicationBar(); 651 fBarWindow->Unlock(); 652 break; 653 } 654 655 case 'TASK': 656 fSwitcherMessenger.SendMessage(message); 657 break; 658 659 case kSuspendSystem: 660 // TODO: Call BRoster? 661 break; 662 663 case kRebootSystem: 664 case kShutdownSystem: 665 { 666 bool reboot = (message->what == kRebootSystem); 667 bool confirm; 668 message->FindBool("confirm", &confirm); 669 670 BRoster roster; 671 BRoster::Private rosterPrivate(roster); 672 status_t error = rosterPrivate.ShutDown(reboot, confirm, false); 673 if (error != B_OK) 674 fprintf(stderr, "Shutdown failed: %s\n", strerror(error)); 675 676 break; 677 } 678 679 case kShowSplash: 680 run_be_about(); 681 break; 682 683 case B_LOCALE_CHANGED: 684 { 685 BLocaleRoster::Default()->Refresh(); 686 687 bool localize; 688 if (message->FindBool("filesys", &localize) == B_OK) 689 gLocalizedNamePreferred = localize; 690 } 691 // fall-through 692 693 case kRealignReplicants: 694 case kShowHideTime: 695 case kShowSeconds: 696 case kShowDayOfWeek: 697 case kShowTimeZone: 698 case kGetClockSettings: 699 fStatusViewMessenger.SendMessage(message); 700 // Notify the replicant tray (through BarView) that the time 701 // interval has changed and it should update the time view 702 // and reflow the tray icons. 703 break; 704 705 default: 706 BApplication::MessageReceived(message); 707 break; 708 } 709 } 710 711 712 void 713 TBarApp::RefsReceived(BMessage* refs) 714 { 715 entry_ref ref; 716 for (int32 i = 0; refs->FindRef("refs", i, &ref) == B_OK; i++) { 717 BMessage refsReceived(B_REFS_RECEIVED); 718 refsReceived.AddRef("refs", &ref); 719 720 BEntry entry(&ref); 721 if (!entry.IsDirectory()) 722 TrackerLaunch(&refsReceived, false); 723 } 724 } 725 726 727 void 728 TBarApp::Subscribe(const BMessenger &subscriber, BList* list) 729 { 730 // called when ExpandoMenuBar, TeamMenu or Switcher are built/rebuilt 731 list->MakeEmpty(); 732 733 BAutolock autolock(sSubscriberLock); 734 if (!autolock.IsLocked()) 735 return; 736 737 int32 numTeams = sBarTeamInfoList.CountItems(); 738 for (int32 i = 0; i < numTeams; i++) { 739 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 740 BarTeamInfo* newBarInfo = new (std::nothrow) BarTeamInfo(*barInfo); 741 if (newBarInfo != NULL) 742 list->AddItem(newBarInfo); 743 } 744 745 int32 subsCount = sSubscribers.CountItems(); 746 for (int32 i = 0; i < subsCount; i++) { 747 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 748 if (*messenger == subscriber) 749 return; 750 } 751 752 sSubscribers.AddItem(new BMessenger(subscriber)); 753 } 754 755 756 void 757 TBarApp::Unsubscribe(const BMessenger &subscriber) 758 { 759 BAutolock autolock(sSubscriberLock); 760 if (!autolock.IsLocked()) 761 return; 762 763 int32 count = sSubscribers.CountItems(); 764 for (int32 i = 0; i < count; i++) { 765 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 766 if (*messenger == subscriber) { 767 sSubscribers.RemoveItem(i); 768 delete messenger; 769 break; 770 } 771 } 772 } 773 774 775 void 776 TBarApp::AddTeam(team_id team, uint32 flags, const char* sig, entry_ref* ref) 777 { 778 if ((flags & B_BACKGROUND_APP) != 0 779 || strcasecmp(sig, kDeskbarSignature) == 0) { 780 // don't add if a background app or Deskbar itself 781 return; 782 } 783 784 BAutolock autolock(sSubscriberLock); 785 if (!autolock.IsLocked()) 786 return; 787 788 // have we already seen this team, is this another instance of 789 // a known app? 790 BarTeamInfo* multiLaunchTeam = NULL; 791 int32 teamCount = sBarTeamInfoList.CountItems(); 792 for (int32 i = 0; i < teamCount; i++) { 793 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 794 if (barInfo->teams->HasItem((void*)(addr_t)team)) 795 return; 796 if (strcasecmp(barInfo->sig, sig) == 0) 797 multiLaunchTeam = barInfo; 798 } 799 800 if (multiLaunchTeam != NULL) { 801 multiLaunchTeam->teams->AddItem((void*)(addr_t)team); 802 803 int32 subsCount = sSubscribers.CountItems(); 804 if (subsCount > 0) { 805 BMessage message(kAddTeam); 806 message.AddInt32("team", team); 807 message.AddString("sig", multiLaunchTeam->sig); 808 809 for (int32 i = 0; i < subsCount; i++) 810 ((BMessenger*)sSubscribers.ItemAt(i))->SendMessage(&message); 811 } 812 return; 813 } 814 815 BFile file(ref, B_READ_ONLY); 816 BAppFileInfo appMime(&file); 817 818 BString name; 819 if (!gLocalizedNamePreferred 820 || BLocaleRoster::Default()->GetLocalizedFileName(name, *ref) 821 != B_OK) { 822 name = ref->name; 823 } 824 825 BarTeamInfo* barInfo = new BarTeamInfo(new BList(), flags, strdup(sig), 826 NULL, strdup(name.String())); 827 FetchAppIcon(barInfo); 828 barInfo->teams->AddItem((void*)(addr_t)team); 829 sBarTeamInfoList.AddItem(barInfo); 830 831 int32 subsCount = sSubscribers.CountItems(); 832 if (subsCount > 0) { 833 for (int32 i = 0; i < subsCount; i++) { 834 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 835 BMessage message(B_SOME_APP_LAUNCHED); 836 837 BList* tList = new BList(*(barInfo->teams)); 838 message.AddPointer("teams", tList); 839 840 BBitmap* icon = new BBitmap(barInfo->icon); 841 ASSERT(icon); 842 843 message.AddPointer("icon", icon); 844 845 message.AddInt32("flags", static_cast<int32>(barInfo->flags)); 846 message.AddString("name", barInfo->name); 847 message.AddString("sig", barInfo->sig); 848 849 messenger->SendMessage(&message); 850 } 851 } 852 } 853 854 855 void 856 TBarApp::RemoveTeam(team_id team) 857 { 858 BAutolock autolock(sSubscriberLock); 859 if (!autolock.IsLocked()) 860 return; 861 862 int32 teamCount = sBarTeamInfoList.CountItems(); 863 for (int32 i = 0; i < teamCount; i++) { 864 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 865 if (barInfo->teams->HasItem((void*)(addr_t)team)) { 866 int32 subsCount = sSubscribers.CountItems(); 867 if (subsCount > 0) { 868 BMessage message((barInfo->teams->CountItems() == 1) 869 ? B_SOME_APP_QUIT : kRemoveTeam); 870 871 message.AddInt32("team", team); 872 for (int32 i = 0; i < subsCount; i++) { 873 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 874 messenger->SendMessage(&message); 875 } 876 } 877 878 barInfo->teams->RemoveItem((void*)(addr_t)team); 879 if (barInfo->teams->CountItems() < 1) { 880 delete (BarTeamInfo*)sBarTeamInfoList.RemoveItem(i); 881 return; 882 } 883 } 884 } 885 } 886 887 888 void 889 TBarApp::ResizeTeamIcons() 890 { 891 for (int32 i = sBarTeamInfoList.CountItems() - 1; i >= 0; i--) { 892 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 893 if ((barInfo->flags & B_BACKGROUND_APP) == 0 894 && strcasecmp(barInfo->sig, kDeskbarSignature) != 0) { 895 FetchAppIcon(barInfo); 896 } 897 } 898 } 899 900 901 int32 902 TBarApp::IconSize() 903 { 904 return fSettings.iconSize; 905 } 906 907 908 void 909 TBarApp::ShowPreferencesWindow() 910 { 911 if (fPreferencesWindow == NULL) { 912 fPreferencesWindow = new PreferencesWindow(BRect(100, 100, 320, 240)); 913 fPreferencesWindow->Show(); 914 } else if (fPreferencesWindow->Lock()) { 915 if (fPreferencesWindow->IsHidden()) 916 fPreferencesWindow->Show(); 917 else 918 fPreferencesWindow->Activate(); 919 920 fPreferencesWindow->Unlock(); 921 } 922 } 923 924 925 void 926 TBarApp::QuitPreferencesWindow() 927 { 928 if (fPreferencesWindow == NULL) 929 return; 930 931 if (fPreferencesWindow->Lock()) { 932 fPreferencesWindow->Quit(); 933 // Quit() destroys the window so don't unlock 934 fPreferencesWindow = NULL; 935 } 936 } 937 938 939 void 940 TBarApp::FetchAppIcon(BarTeamInfo* barInfo) 941 { 942 int32 width = IconSize(); 943 int32 index = (width - kMinimumIconSize) / kIconSizeInterval; 944 945 // first look in the icon cache 946 barInfo->icon = barInfo->iconCache[index]; 947 if (barInfo->icon != NULL) 948 return; 949 950 // icon wasn't in cache, get it from be_roster and cache it 951 app_info appInfo; 952 icon_size size = width >= 31 ? B_LARGE_ICON : B_MINI_ICON; 953 BBitmap* icon = new BBitmap(IconRect(), kIconColorSpace); 954 if (be_roster->GetAppInfo(barInfo->sig, &appInfo) == B_OK) { 955 // fetch the app icon 956 BFile file(&appInfo.ref, B_READ_ONLY); 957 BAppFileInfo appMime(&file); 958 if (appMime.GetIcon(icon, size) == B_OK) { 959 delete barInfo->iconCache[index]; 960 barInfo->iconCache[index] = barInfo->icon = icon; 961 return; 962 } 963 } 964 965 // couldn't find the app icon 966 // fetch the generic 3 boxes icon and cache it 967 BMimeType defaultAppMime; 968 defaultAppMime.SetTo(B_APP_MIME_TYPE); 969 if (defaultAppMime.GetIcon(icon, size) == B_OK) { 970 delete barInfo->iconCache[index]; 971 barInfo->iconCache[index] = barInfo->icon = icon; 972 return; 973 } 974 975 // couldn't find generic 3 boxes icon 976 // fill with transparent 977 uint8* iconBits = (uint8*)icon->Bits(); 978 if (icon->ColorSpace() == B_RGBA32) { 979 int32 i = 0; 980 while (i < icon->BitsLength()) { 981 iconBits[i++] = B_TRANSPARENT_32_BIT.red; 982 iconBits[i++] = B_TRANSPARENT_32_BIT.green; 983 iconBits[i++] = B_TRANSPARENT_32_BIT.blue; 984 iconBits[i++] = B_TRANSPARENT_32_BIT.alpha; 985 } 986 } else { 987 // Assume B_CMAP8 988 for (int32 i = 0; i < icon->BitsLength(); i++) 989 iconBits[i] = B_TRANSPARENT_MAGIC_CMAP8; 990 } 991 992 delete barInfo->iconCache[index]; 993 barInfo->iconCache[index] = barInfo->icon = icon; 994 } 995 996 997 BRect 998 TBarApp::IconRect() 999 { 1000 int32 iconSize = IconSize(); 1001 return BRect(0, 0, iconSize - 1, iconSize - 1); 1002 } 1003 1004 1005 // #pragma mark - 1006 1007 1008 BarTeamInfo::BarTeamInfo(BList* teams, uint32 flags, char* sig, BBitmap* icon, 1009 char* name) 1010 : 1011 teams(teams), 1012 flags(flags), 1013 sig(sig), 1014 icon(icon), 1015 name(name) 1016 { 1017 _Init(); 1018 } 1019 1020 1021 BarTeamInfo::BarTeamInfo(const BarTeamInfo &info) 1022 : 1023 teams(new BList(*info.teams)), 1024 flags(info.flags), 1025 sig(strdup(info.sig)), 1026 icon(new BBitmap(*info.icon)), 1027 name(strdup(info.name)) 1028 { 1029 _Init(); 1030 } 1031 1032 1033 BarTeamInfo::~BarTeamInfo() 1034 { 1035 delete teams; 1036 free(sig); 1037 free(name); 1038 for (int32 i = 0; i < kIconCacheCount; i++) 1039 delete iconCache[i]; 1040 } 1041 1042 1043 void 1044 BarTeamInfo::_Init() 1045 { 1046 for (int32 i = 0; i < kIconCacheCount; i++) 1047 iconCache[i] = NULL; 1048 } 1049