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