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