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 <ControlLook.h> 47 #include <Debug.h> 48 #include <Directory.h> 49 #include <Dragger.h> 50 #include <File.h> 51 #include <FindDirectory.h> 52 #include <IconUtils.h> 53 #include <Locale.h> 54 #include <Message.h> 55 #include <Messenger.h> 56 #include <Mime.h> 57 #include <Path.h> 58 #include <Roster.h> 59 60 #include <DeskbarPrivate.h> 61 #include <RosterPrivate.h> 62 #include "tracker_private.h" 63 64 #include "BarView.h" 65 #include "BarWindow.h" 66 #include "DeskbarUtils.h" 67 #include "FSUtils.h" 68 #include "PreferencesWindow.h" 69 #include "ResourceSet.h" 70 #include "StatusView.h" 71 #include "Switcher.h" 72 73 #include "icons.h" 74 75 76 BLocker TBarApp::sSubscriberLock; 77 BList TBarApp::sBarTeamInfoList; 78 BList TBarApp::sWindowIconCache; 79 BList TBarApp::sSubscribers; 80 81 82 const uint32 kShowDeskbarMenu = 'BeMn'; 83 const uint32 kShowTeamMenu = 'TmMn'; 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 sWindowIconCache.MakeEmpty(); 131 for (int32 id = R_WindowShownIcon; id <= R_WindowHiddenSwitchIcon; id++) { 132 if (id == R_ResizeIcon) 133 continue; 134 135 WindowIconCache* winCache = new WindowIconCache(id); 136 _CacheWindowIcon(winCache); 137 sWindowIconCache.AddItem(winCache); 138 } 139 140 sSubscribers.MakeEmpty(); 141 fSwitcherMessenger = BMessenger(new TSwitchManager()); 142 fBarWindow->Show(); 143 144 fBarWindow->Lock(); 145 fBarView->UpdatePlacement(); 146 fBarWindow->Unlock(); 147 148 // this messenger now targets the barview instead of the 149 // statusview so that all additions to the tray 150 // follow the same path 151 fStatusViewMessenger = BMessenger(fBarWindow->FindView("BarView")); 152 } 153 154 155 TBarApp::~TBarApp() 156 { 157 be_roster->StopWatching(this); 158 159 int32 teamCount = sBarTeamInfoList.CountItems(); 160 for (int32 i = 0; i < teamCount; i++) { 161 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 162 delete barInfo; 163 } 164 165 int32 subsCount = sSubscribers.CountItems(); 166 for (int32 i = 0; i < subsCount; i++) { 167 BMessenger* messenger 168 = static_cast<BMessenger*>(sSubscribers.ItemAt(i)); 169 delete messenger; 170 } 171 172 SaveSettings(); 173 174 delete fSettingsFile; 175 delete fClockSettingsFile; 176 } 177 178 179 bool 180 TBarApp::QuitRequested() 181 { 182 // don't allow the user to quit 183 if (CurrentMessage() && CurrentMessage()->FindBool("shortcut")) { 184 // but close the preferences window 185 QuitPreferencesWindow(); 186 return false; 187 } 188 189 // system quitting, call inherited to notify all loopers 190 fBarWindow->SaveSettings(); 191 BApplication::QuitRequested(); 192 return true; 193 } 194 195 196 void 197 TBarApp::SaveSettings() 198 { 199 if (fSettingsFile->InitCheck() == B_OK) { 200 fSettingsFile->Seek(0, SEEK_SET); 201 BMessage prefs; 202 prefs.AddBool("vertical", fSettings.vertical); 203 prefs.AddBool("left", fSettings.left); 204 prefs.AddBool("top", fSettings.top); 205 prefs.AddInt32("state", fSettings.state); 206 prefs.AddFloat("width", fSettings.width); 207 prefs.AddPoint("switcherLoc", fSettings.switcherLoc); 208 prefs.AddBool("showClock", fSettings.showClock); 209 // applications 210 prefs.AddBool("trackerAlwaysFirst", fSettings.trackerAlwaysFirst); 211 prefs.AddBool("sortRunningApps", fSettings.sortRunningApps); 212 prefs.AddBool("superExpando", fSettings.superExpando); 213 prefs.AddBool("expandNewTeams", fSettings.expandNewTeams); 214 prefs.AddBool("hideLabels", fSettings.hideLabels); 215 prefs.AddInt32("iconSize", fSettings.iconSize); 216 // recent items 217 prefs.AddBool("recentDocsEnabled", fSettings.recentDocsEnabled); 218 prefs.AddBool("recentFoldersEnabled", fSettings.recentFoldersEnabled); 219 prefs.AddBool("recentAppsEnabled", fSettings.recentAppsEnabled); 220 prefs.AddInt32("recentDocsCount", fSettings.recentDocsCount); 221 prefs.AddInt32("recentFoldersCount", fSettings.recentFoldersCount); 222 prefs.AddInt32("recentAppsCount", fSettings.recentAppsCount); 223 // window 224 prefs.AddBool("alwaysOnTop", fSettings.alwaysOnTop); 225 prefs.AddBool("autoRaise", fSettings.autoRaise); 226 prefs.AddBool("autoHide", fSettings.autoHide); 227 228 prefs.Flatten(fSettingsFile); 229 } 230 231 if (fClockSettingsFile->InitCheck() == B_OK) { 232 fClockSettingsFile->Seek(0, SEEK_SET); 233 BMessage prefs; 234 prefs.AddBool("showSeconds", fClockSettings.showSeconds); 235 prefs.AddBool("showDayOfWeek", fClockSettings.showDayOfWeek); 236 prefs.AddBool("showTimeZone", fClockSettings.showTimeZone); 237 238 prefs.Flatten(fClockSettingsFile); 239 } 240 } 241 242 243 void 244 TBarApp::InitSettings() 245 { 246 // compute metrics 247 sIconGap = ceilf(be_control_look->DefaultLabelSpacing() / 3.0f); 248 249 gDragRegionWidth = be_control_look->ComposeSpacing(B_USE_HALF_ITEM_SPACING); 250 gDragWidth = ceilf(gDragRegionWidth * 0.6f); 251 252 gMinReplicantHeight = gMinReplicantWidth = 253 be_control_look->ComposeIconSize(B_MINI_ICON).IntegerWidth() + 1; 254 255 // 1 pixel for left gutter 256 // space for replicant tray (6 items) 257 // 6 pixel drag region 258 gMinimumTrayWidth = sIconGap + gMinReplicantWidth 259 + (kMinimumReplicantCount * sIconGap) 260 + (kMinimumReplicantCount * gMinReplicantWidth) + kGutter; 261 262 gMinimumWindowWidth = kGutter + gMinimumTrayWidth + gDragRegionWidth; 263 gMaximumWindowWidth = gMinimumWindowWidth * 2; 264 265 // defaults 266 desk_settings settings; 267 settings.vertical = fDefaultSettings.vertical = true; 268 settings.left = fDefaultSettings.left = false; 269 settings.top = fDefaultSettings.top = true; 270 settings.state = fDefaultSettings.state = kExpandoState; 271 settings.width = fDefaultSettings.width = gMinimumWindowWidth; 272 settings.switcherLoc = fDefaultSettings.switcherLoc = BPoint(5000, 5000); 273 settings.showClock = fDefaultSettings.showClock = true; 274 // applications 275 settings.trackerAlwaysFirst = fDefaultSettings.trackerAlwaysFirst = true; 276 settings.sortRunningApps = fDefaultSettings.sortRunningApps = false; 277 settings.superExpando = fDefaultSettings.superExpando = false; 278 settings.expandNewTeams = fDefaultSettings.expandNewTeams = false; 279 settings.hideLabels = fDefaultSettings.hideLabels = false; 280 settings.iconSize = fDefaultSettings.iconSize = kMinimumIconSize; 281 // recent items 282 settings.recentDocsEnabled = fDefaultSettings.recentDocsEnabled = true; 283 settings.recentFoldersEnabled 284 = fDefaultSettings.recentFoldersEnabled = true; 285 settings.recentAppsEnabled = fDefaultSettings.recentAppsEnabled = true; 286 settings.recentDocsCount = fDefaultSettings.recentDocsCount = 10; 287 settings.recentFoldersCount = fDefaultSettings.recentFoldersCount = 10; 288 settings.recentAppsCount = fDefaultSettings.recentAppsCount = 10; 289 // window 290 settings.alwaysOnTop = fDefaultSettings.alwaysOnTop = false; 291 settings.autoRaise = fDefaultSettings.autoRaise = false; 292 settings.autoHide = fDefaultSettings.autoHide = false; 293 294 clock_settings clock; 295 clock.showSeconds = false; 296 clock.showDayOfWeek = false; 297 clock.showTimeZone = false; 298 299 BPath dirPath; 300 const char* settingsFileName = "settings"; 301 const char* clockSettingsFileName = "clock_settings"; 302 303 find_directory(B_USER_DESKBAR_DIRECTORY, &dirPath, true); 304 // just make it 305 306 if (GetDeskbarSettingsDirectory(dirPath, true) == B_OK) { 307 BPath filePath = dirPath; 308 filePath.Append(settingsFileName); 309 fSettingsFile = new BFile(filePath.Path(), O_RDWR); 310 if (fSettingsFile->InitCheck() != B_OK) { 311 BDirectory theDir(dirPath.Path()); 312 if (theDir.InitCheck() == B_OK) 313 theDir.CreateFile(settingsFileName, fSettingsFile); 314 } 315 316 BMessage prefs; 317 if (fSettingsFile->InitCheck() == B_OK 318 && prefs.Unflatten(fSettingsFile) == B_OK) { 319 settings.vertical = prefs.GetBool("vertical", 320 fDefaultSettings.vertical); 321 settings.left = prefs.GetBool("left", 322 fDefaultSettings.left); 323 settings.top = prefs.GetBool("top", 324 fDefaultSettings.top); 325 settings.state = prefs.GetInt32("state", 326 fDefaultSettings.state); 327 settings.width = prefs.GetFloat("width", 328 fDefaultSettings.width); 329 settings.switcherLoc = prefs.GetPoint("switcherLoc", 330 fDefaultSettings.switcherLoc); 331 settings.showClock = prefs.GetBool("showClock", 332 fDefaultSettings.showClock); 333 // applications 334 settings.trackerAlwaysFirst = prefs.GetBool("trackerAlwaysFirst", 335 fDefaultSettings.trackerAlwaysFirst); 336 settings.sortRunningApps = prefs.GetBool("sortRunningApps", 337 fDefaultSettings.sortRunningApps); 338 settings.superExpando = prefs.GetBool("superExpando", 339 fDefaultSettings.superExpando); 340 settings.expandNewTeams = prefs.GetBool("expandNewTeams", 341 fDefaultSettings.expandNewTeams); 342 settings.hideLabels = prefs.GetBool("hideLabels", 343 fDefaultSettings.hideLabels); 344 settings.iconSize = prefs.GetInt32("iconSize", 345 fDefaultSettings.iconSize); 346 // recent items 347 settings.recentDocsEnabled = prefs.GetBool("recentDocsEnabled", 348 fDefaultSettings.recentDocsEnabled); 349 settings.recentFoldersEnabled 350 = prefs.GetBool("recentFoldersEnabled", 351 fDefaultSettings.recentFoldersEnabled); 352 settings.recentAppsEnabled = prefs.GetBool("recentAppsEnabled", 353 fDefaultSettings.recentAppsEnabled); 354 settings.recentDocsCount = prefs.GetInt32("recentDocsCount", 355 fDefaultSettings.recentDocsCount); 356 settings.recentFoldersCount = prefs.GetInt32("recentFoldersCount", 357 fDefaultSettings.recentFoldersCount); 358 settings.recentAppsCount = prefs.GetInt32("recentAppsCount", 359 fDefaultSettings.recentAppsCount); 360 // window 361 settings.alwaysOnTop = prefs.GetBool("alwaysOnTop", 362 fDefaultSettings.alwaysOnTop); 363 settings.autoRaise = prefs.GetBool("autoRaise", 364 fDefaultSettings.autoRaise); 365 settings.autoHide = prefs.GetBool("autoHide", 366 fDefaultSettings.autoHide); 367 } 368 369 // constrain width setting within limits 370 if (settings.width < gMinimumWindowWidth) 371 settings.width = gMinimumWindowWidth; 372 else if (settings.width > gMaximumWindowWidth) 373 settings.width = gMaximumWindowWidth; 374 375 filePath = dirPath; 376 filePath.Append(clockSettingsFileName); 377 fClockSettingsFile = new BFile(filePath.Path(), O_RDWR); 378 if (fClockSettingsFile->InitCheck() != B_OK) { 379 BDirectory theDir(dirPath.Path()); 380 if (theDir.InitCheck() == B_OK) 381 theDir.CreateFile(clockSettingsFileName, fClockSettingsFile); 382 } 383 384 if (fClockSettingsFile->InitCheck() == B_OK 385 && prefs.Unflatten(fClockSettingsFile) == B_OK) { 386 clock.showSeconds = prefs.GetBool("showSeconds", false); 387 clock.showDayOfWeek = prefs.GetBool("showDayOfWeek", false); 388 clock.showTimeZone = prefs.GetBool("showTimeZone", false); 389 } 390 } 391 392 fSettings = settings; 393 fClockSettings = clock; 394 } 395 396 397 void 398 TBarApp::MessageReceived(BMessage* message) 399 { 400 switch (message->what) { 401 // BDeskbar originating messages we can handle 402 case kMsgIsAlwaysOnTop: 403 { 404 BMessage reply('rply'); 405 reply.AddBool("always on top", fSettings.alwaysOnTop); 406 message->SendReply(&reply); 407 break; 408 } 409 case kMsgIsAutoRaise: 410 { 411 BMessage reply('rply'); 412 reply.AddBool("auto raise", fSettings.autoRaise); 413 message->SendReply(&reply); 414 break; 415 } 416 case kMsgIsAutoHide: 417 { 418 BMessage reply('rply'); 419 reply.AddBool("auto hide", fSettings.autoHide); 420 message->SendReply(&reply); 421 break; 422 } 423 424 // pass rest of BDeskbar originating messages onto the window 425 // (except for setters handled below) 426 case kMsgLocation: 427 case kMsgSetLocation: 428 case kMsgIsExpanded: 429 case kMsgExpand: 430 case kMsgGetItemInfo: 431 case kMsgHasItem: 432 case kMsgCountItems: 433 case kMsgMaxItemSize: 434 case kMsgAddView: 435 case kMsgRemoveItem: 436 case kMsgAddAddOn: 437 fBarWindow->PostMessage(message); 438 break; 439 440 case kConfigShow: 441 ShowPreferencesWindow(); 442 break; 443 444 case kConfigQuit: 445 QuitPreferencesWindow(); 446 break; 447 448 case kStateChanged: 449 if (fPreferencesWindow != NULL) 450 fPreferencesWindow->PostMessage(kStateChanged); 451 break; 452 453 case kShowDeskbarMenu: 454 if (fBarWindow->Lock()) { 455 fBarWindow->ShowDeskbarMenu(); 456 fBarWindow->Unlock(); 457 } 458 break; 459 460 case kShowTeamMenu: 461 if (fBarWindow->Lock()) { 462 fBarWindow->ShowTeamMenu(); 463 fBarWindow->Unlock(); 464 } 465 break; 466 467 case kUpdateRecentCounts: 468 int32 count; 469 bool enabled; 470 471 if (message->FindInt32("applications", &count) == B_OK) 472 fSettings.recentAppsCount = count; 473 if (message->FindBool("applicationsEnabled", &enabled) == B_OK) 474 fSettings.recentAppsEnabled = enabled && count > 0; 475 476 if (message->FindInt32("folders", &count) == B_OK) 477 fSettings.recentFoldersCount = count; 478 if (message->FindBool("foldersEnabled", &enabled) == B_OK) 479 fSettings.recentFoldersEnabled = enabled && count > 0; 480 481 if (message->FindInt32("documents", &count) == B_OK) 482 fSettings.recentDocsCount = count; 483 if (message->FindBool("documentsEnabled", &enabled) == B_OK) 484 fSettings.recentDocsEnabled = enabled && count > 0; 485 486 if (fPreferencesWindow != NULL) 487 fPreferencesWindow->PostMessage(kUpdatePreferences); 488 break; 489 490 case B_SOME_APP_LAUNCHED: 491 { 492 team_id team = -1; 493 message->FindInt32("be:team", &team); 494 495 uint32 flags = 0; 496 message->FindInt32("be:flags", (int32*)&flags); 497 498 const char* signature = NULL; 499 message->FindString("be:signature", &signature); 500 501 entry_ref ref; 502 message->FindRef("be:ref", &ref); 503 504 AddTeam(team, flags, signature, &ref); 505 break; 506 } 507 508 case B_SOME_APP_QUIT: 509 { 510 team_id team = -1; 511 message->FindInt32("be:team", &team); 512 RemoveTeam(team); 513 break; 514 } 515 516 case B_ARCHIVED_OBJECT: 517 // TODO: what's this??? 518 message->AddString("special", "Alex Osadzinski"); 519 fStatusViewMessenger.SendMessage(message); 520 break; 521 522 case kToggleDraggers: 523 if (BDragger::AreDraggersDrawn()) 524 BDragger::HideAllDraggers(); 525 else 526 BDragger::ShowAllDraggers(); 527 break; 528 529 case kMsgAlwaysOnTop: // from BDeskbar 530 case kAlwaysTop: 531 fSettings.alwaysOnTop = !fSettings.alwaysOnTop; 532 533 if (fPreferencesWindow != NULL) 534 fPreferencesWindow->PostMessage(kUpdatePreferences); 535 536 fBarWindow->SetFeel(fSettings.alwaysOnTop 537 ? B_FLOATING_ALL_WINDOW_FEEL 538 : B_NORMAL_WINDOW_FEEL); 539 break; 540 541 case kMsgAutoRaise: // from BDeskbar 542 case kAutoRaise: 543 fSettings.autoRaise = fSettings.alwaysOnTop ? false 544 : !fSettings.autoRaise; 545 546 if (fPreferencesWindow != NULL) 547 fPreferencesWindow->PostMessage(kUpdatePreferences); 548 break; 549 550 case kMsgAutoHide: // from BDeskbar 551 case kAutoHide: 552 fSettings.autoHide = !fSettings.autoHide; 553 554 if (fPreferencesWindow != NULL) 555 fPreferencesWindow->PostMessage(kUpdatePreferences); 556 557 fBarWindow->Lock(); 558 fBarView->HideDeskbar(fSettings.autoHide); 559 fBarWindow->Unlock(); 560 break; 561 562 case kTrackerFirst: 563 fSettings.trackerAlwaysFirst = !fSettings.trackerAlwaysFirst; 564 565 if (fPreferencesWindow != NULL) 566 fPreferencesWindow->PostMessage(kUpdatePreferences); 567 568 // if mini mode we don't need to update the view 569 if (fBarView->MiniState()) 570 break; 571 572 fBarWindow->Lock(); 573 fBarView->PlaceApplicationBar(); 574 fBarWindow->Unlock(); 575 break; 576 577 case kSortRunningApps: 578 fSettings.sortRunningApps = !fSettings.sortRunningApps; 579 580 if (fPreferencesWindow != NULL) 581 fPreferencesWindow->PostMessage(kUpdatePreferences); 582 583 // if mini mode we don't need to update the view 584 if (fBarView->MiniState()) 585 break; 586 587 fBarWindow->Lock(); 588 fBarView->PlaceApplicationBar(); 589 fBarWindow->Unlock(); 590 break; 591 592 case kUnsubscribe: 593 { 594 BMessenger messenger; 595 if (message->FindMessenger("messenger", &messenger) == B_OK) 596 Unsubscribe(messenger); 597 break; 598 } 599 600 case kSuperExpando: 601 fSettings.superExpando = !fSettings.superExpando; 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 kExpandNewTeams: 616 fSettings.expandNewTeams = !fSettings.expandNewTeams; 617 618 if (fPreferencesWindow != NULL) 619 fPreferencesWindow->PostMessage(kUpdatePreferences); 620 621 // if mini mode we don't need to update the view 622 if (fBarView->MiniState()) 623 break; 624 625 fBarWindow->Lock(); 626 fBarView->PlaceApplicationBar(); 627 fBarWindow->Unlock(); 628 break; 629 630 case kHideLabels: 631 fSettings.hideLabels = !fSettings.hideLabels; 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 fBarView->PlaceApplicationBar(); 642 fBarWindow->Unlock(); 643 break; 644 645 case kResizeTeamIcons: 646 { 647 int32 oldIconSize = fSettings.iconSize; 648 int32 value; 649 if (message->FindInt32("be:value", &value) != B_OK) 650 break; 651 652 int32 iconSize = value * kIconSizeInterval; 653 fSettings.iconSize = iconSize; 654 655 // pin icon size between min and max values 656 if (fSettings.iconSize < kMinimumIconSize) 657 fSettings.iconSize = kMinimumIconSize; 658 else if (fSettings.iconSize > kMaximumIconSize) 659 fSettings.iconSize = kMaximumIconSize; 660 661 // don't resize if icon size hasn't changed 662 if (fSettings.iconSize == oldIconSize) 663 break; 664 665 ResizeTeamIcons(); 666 667 if (fPreferencesWindow != NULL) 668 fPreferencesWindow->PostMessage(kUpdatePreferences); 669 670 // if mini mode we don't need to update the view 671 if (fBarView->MiniState()) 672 break; 673 674 fBarWindow->Lock(); 675 if (!fBarView->Vertical()) { 676 // Must also resize the Deskbar menu and replicant tray in 677 // horizontal mode 678 fBarView->PlaceDeskbarMenu(); 679 fBarView->PlaceTray(false, false); 680 } 681 fBarView->PlaceApplicationBar(); 682 fBarWindow->Unlock(); 683 break; 684 } 685 686 case 'TASK': 687 fSwitcherMessenger.SendMessage(message); 688 break; 689 690 case kSuspendSystem: 691 // TODO: Call BRoster? 692 break; 693 694 case kRebootSystem: 695 case kShutdownSystem: 696 { 697 bool reboot = (message->what == kRebootSystem); 698 bool confirm; 699 message->FindBool("confirm", &confirm); 700 701 BRoster roster; 702 BRoster::Private rosterPrivate(roster); 703 status_t error = rosterPrivate.ShutDown(reboot, confirm, false); 704 if (error != B_OK) 705 fprintf(stderr, "Shutdown failed: %s\n", strerror(error)); 706 707 break; 708 } 709 710 case kShowSplash: 711 run_be_about(); 712 break; 713 714 case B_LOCALE_CHANGED: 715 { 716 BLocaleRoster::Default()->Refresh(); 717 718 bool localize; 719 if (message->FindBool("filesys", &localize) == B_OK) 720 gLocalizedNamePreferred = localize; 721 } 722 // fall-through 723 724 case kRealignReplicants: 725 case kShowHideTime: 726 case kShowSeconds: 727 case kShowDayOfWeek: 728 case kShowTimeZone: 729 case kGetClockSettings: 730 fStatusViewMessenger.SendMessage(message); 731 // Notify the replicant tray (through BarView) that the time 732 // interval has changed and it should update the time view 733 // and reflow the tray icons. 734 break; 735 736 default: 737 BApplication::MessageReceived(message); 738 break; 739 } 740 } 741 742 743 void 744 TBarApp::RefsReceived(BMessage* refs) 745 { 746 entry_ref ref; 747 for (int32 i = 0; refs->FindRef("refs", i, &ref) == B_OK; i++) { 748 BMessage refsReceived(B_REFS_RECEIVED); 749 refsReceived.AddRef("refs", &ref); 750 751 BEntry entry(&ref); 752 if (!entry.IsDirectory()) 753 TrackerLaunch(&refsReceived, false); 754 } 755 } 756 757 758 void 759 TBarApp::Subscribe(const BMessenger &subscriber, BList* list) 760 { 761 // called when ExpandoMenuBar, TeamMenu or Switcher are built/rebuilt 762 list->MakeEmpty(); 763 764 BAutolock autolock(sSubscriberLock); 765 if (!autolock.IsLocked()) 766 return; 767 768 int32 numTeams = sBarTeamInfoList.CountItems(); 769 for (int32 i = 0; i < numTeams; i++) { 770 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 771 BarTeamInfo* newBarInfo = new(std::nothrow) BarTeamInfo(*barInfo); 772 if (newBarInfo != NULL) 773 list->AddItem(newBarInfo); 774 } 775 776 int32 subsCount = sSubscribers.CountItems(); 777 for (int32 i = 0; i < subsCount; i++) { 778 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 779 if (*messenger == subscriber) 780 return; 781 } 782 783 sSubscribers.AddItem(new BMessenger(subscriber)); 784 } 785 786 787 void 788 TBarApp::Unsubscribe(const BMessenger &subscriber) 789 { 790 BAutolock autolock(sSubscriberLock); 791 if (!autolock.IsLocked()) 792 return; 793 794 int32 count = sSubscribers.CountItems(); 795 for (int32 i = 0; i < count; i++) { 796 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 797 if (*messenger == subscriber) { 798 sSubscribers.RemoveItem(i); 799 delete messenger; 800 break; 801 } 802 } 803 } 804 805 806 BBitmap* 807 TBarApp::FetchTeamIcon(team_id team, int32 size) 808 { 809 int32 teamCount = sBarTeamInfoList.CountItems(); 810 for (int32 i = 0; i < teamCount; i++) { 811 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 812 if (barInfo->teams->HasItem((void*)(addr_t)team)) { 813 _CacheTeamIcon(barInfo, size); 814 BBitmap* icon = barInfo->icon; 815 816 // restore icon pointer back to setting 817 if (size != fSettings.iconSize) { 818 int32 index = (fSettings.iconSize - kMinimumIconSize) 819 / kIconSizeInterval; 820 barInfo->icon = barInfo->iconCache[index]; 821 } 822 823 return icon; 824 } 825 } 826 827 return NULL; 828 } 829 830 831 BBitmap* 832 TBarApp::FetchWindowIcon(bool local, bool minimized) 833 { 834 int32 id = R_WindowShownIcon; 835 int32 index = 0; 836 837 if (local) { 838 if (!minimized) { 839 id = R_WindowShownIcon; 840 index = 0; 841 } 842 else { 843 id = R_WindowHiddenIcon; 844 index = 1; 845 } 846 } else { 847 if (!minimized) { 848 id = R_WindowShownSwitchIcon; 849 index = 2; 850 } 851 else { 852 id = R_WindowHiddenSwitchIcon; 853 index = 3; 854 } 855 } 856 857 // create a new cache entry if not found 858 WindowIconCache* winCache 859 = (WindowIconCache*)sWindowIconCache.ItemAt(index); 860 if (winCache == NULL) 861 winCache = new WindowIconCache(id); 862 863 _CacheWindowIcon(winCache); 864 865 return winCache->icon; 866 } 867 868 869 void 870 TBarApp::AddTeam(team_id team, uint32 flags, const char* sig, entry_ref* ref) 871 { 872 if ((flags & B_BACKGROUND_APP) != 0 873 || strcasecmp(sig, kDeskbarSignature) == 0) { 874 // don't add if a background app or Deskbar itself 875 return; 876 } 877 878 BAutolock autolock(sSubscriberLock); 879 if (!autolock.IsLocked()) 880 return; 881 882 // have we already seen this team, is this another instance of 883 // a known app? 884 BarTeamInfo* multiLaunchTeam = NULL; 885 int32 teamCount = sBarTeamInfoList.CountItems(); 886 for (int32 i = 0; i < teamCount; i++) { 887 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 888 if (barInfo->teams->HasItem((void*)(addr_t)team)) 889 return; 890 if (strcasecmp(barInfo->sig, sig) == 0) 891 multiLaunchTeam = barInfo; 892 } 893 894 if (multiLaunchTeam != NULL) { 895 multiLaunchTeam->teams->AddItem((void*)(addr_t)team); 896 897 int32 subsCount = sSubscribers.CountItems(); 898 if (subsCount > 0) { 899 BMessage message(kAddTeam); 900 message.AddInt32("team", team); 901 message.AddString("sig", multiLaunchTeam->sig); 902 903 for (int32 i = 0; i < subsCount; i++) 904 ((BMessenger*)sSubscribers.ItemAt(i))->SendMessage(&message); 905 } 906 return; 907 } 908 909 BString name; 910 if (!gLocalizedNamePreferred 911 || BLocaleRoster::Default()->GetLocalizedFileName(name, *ref) 912 != B_OK) { 913 name = ref->name; 914 } 915 916 BarTeamInfo* barInfo = new BarTeamInfo(new BList(), flags, strdup(sig), 917 strdup(name.String())); 918 _CacheTeamIcon(barInfo); 919 barInfo->teams->AddItem((void*)(addr_t)team); 920 sBarTeamInfoList.AddItem(barInfo); 921 922 int32 subsCount = sSubscribers.CountItems(); 923 if (subsCount > 0) { 924 for (int32 i = 0; i < subsCount; i++) { 925 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 926 BMessage message(B_SOME_APP_LAUNCHED); 927 928 BList* tList = new BList(*(barInfo->teams)); 929 message.AddPointer("teams", tList); 930 931 BBitmap* icon = new BBitmap(barInfo->icon); 932 ASSERT(icon); 933 934 message.AddPointer("icon", icon); 935 936 message.AddInt32("flags", static_cast<int32>(barInfo->flags)); 937 message.AddString("name", barInfo->name); 938 message.AddString("sig", barInfo->sig); 939 940 messenger->SendMessage(&message); 941 } 942 } 943 } 944 945 946 void 947 TBarApp::RemoveTeam(team_id team) 948 { 949 BAutolock autolock(sSubscriberLock); 950 if (!autolock.IsLocked()) 951 return; 952 953 int32 teamCount = sBarTeamInfoList.CountItems(); 954 for (int32 i = 0; i < teamCount; i++) { 955 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 956 if (barInfo->teams->HasItem((void*)(addr_t)team)) { 957 int32 subsCount = sSubscribers.CountItems(); 958 if (subsCount > 0) { 959 BMessage message((barInfo->teams->CountItems() == 1) 960 ? B_SOME_APP_QUIT : kRemoveTeam); 961 962 message.AddInt32("team", team); 963 for (int32 i = 0; i < subsCount; i++) { 964 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i); 965 messenger->SendMessage(&message); 966 } 967 } 968 969 barInfo->teams->RemoveItem((void*)(addr_t)team); 970 if (barInfo->teams->CountItems() < 1) { 971 delete (BarTeamInfo*)sBarTeamInfoList.RemoveItem(i); 972 return; 973 } 974 } 975 } 976 } 977 978 979 void 980 TBarApp::ResizeTeamIcons() 981 { 982 for (int32 i = sBarTeamInfoList.CountItems() - 1; i >= 0; i--) { 983 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i); 984 if ((barInfo->flags & B_BACKGROUND_APP) == 0 985 && strcasecmp(barInfo->sig, kDeskbarSignature) != 0) { 986 _CacheTeamIcon(barInfo); 987 } 988 } 989 } 990 991 992 int32 993 TBarApp::TeamIconSize() 994 { 995 static int32 iconSize = 0, composed = 0; 996 int32 saved = fSettings.iconSize; 997 if (iconSize != saved) { 998 composed = be_control_look->ComposeIconSize(saved).IntegerWidth() + 1; 999 iconSize = saved; 1000 } 1001 1002 return composed; 1003 } 1004 1005 1006 void 1007 TBarApp::ShowPreferencesWindow() 1008 { 1009 if (fPreferencesWindow == NULL) { 1010 fPreferencesWindow = new PreferencesWindow(BRect(100, 100, 320, 240)); 1011 fPreferencesWindow->Show(); 1012 } else if (fPreferencesWindow->Lock()) { 1013 if (fPreferencesWindow->IsHidden()) 1014 fPreferencesWindow->Show(); 1015 else 1016 fPreferencesWindow->Activate(); 1017 1018 fPreferencesWindow->Unlock(); 1019 } 1020 } 1021 1022 1023 void 1024 TBarApp::QuitPreferencesWindow() 1025 { 1026 if (fPreferencesWindow == NULL) 1027 return; 1028 1029 if (fPreferencesWindow->Lock()) { 1030 fPreferencesWindow->Quit(); 1031 // Quit() destroys the window so don't unlock 1032 fPreferencesWindow = NULL; 1033 } 1034 } 1035 1036 1037 status_t 1038 TBarApp::_CacheTeamIcon(BarTeamInfo* barInfo) 1039 { 1040 if (barInfo == NULL) 1041 return B_BAD_VALUE; 1042 1043 return _CacheTeamIcon(barInfo, fSettings.iconSize); 1044 } 1045 1046 1047 status_t 1048 TBarApp::_CacheTeamIcon(BarTeamInfo* barInfo, int32 size) 1049 { 1050 if (barInfo == NULL || size < kMinimumIconSize) 1051 return B_BAD_VALUE; 1052 1053 // icon index based on icon size 1054 const int32 index = (size - kMinimumIconSize) / kIconSizeInterval; 1055 1056 // first look in the icon cache 1057 barInfo->icon = barInfo->iconCache[index]; 1058 if (barInfo->icon != NULL) 1059 return B_OK; 1060 1061 int32 composed = be_control_look->ComposeIconSize(size).IntegerWidth() + 1; 1062 BRect iconRect = BRect(0, 0, composed - 1, composed - 1); 1063 BBitmap* icon = new BBitmap(iconRect, B_RGBA32); 1064 1065 // icon wasn't in cache, get it from be_roster and cache it 1066 app_info appInfo; 1067 if (be_roster->GetAppInfo(barInfo->sig, &appInfo) == B_OK) { 1068 // fetch the app icon 1069 BFile file(&appInfo.ref, B_READ_ONLY); 1070 BAppFileInfo appMime(&file); 1071 if (appMime.GetIcon(icon, (icon_size)size) == B_OK) { 1072 barInfo->iconCache[index] = barInfo->icon = icon; 1073 1074 return B_OK; 1075 } 1076 } 1077 1078 // couldn't find the app icon 1079 // fetch the generic 3 boxes icon and cache it 1080 BMimeType defaultAppMime; 1081 defaultAppMime.SetTo(B_APP_MIME_TYPE); 1082 if (defaultAppMime.GetIcon(icon, (icon_size)size) == B_OK) { 1083 barInfo->iconCache[index] = barInfo->icon = icon; 1084 1085 return B_OK; 1086 } 1087 1088 // couldn't find generic 3 boxes icon 1089 // fill with transparent 1090 uint8* iconBits = (uint8*)icon->Bits(); 1091 if (icon->ColorSpace() == B_RGBA32) { 1092 int32 i = 0; 1093 while (i < icon->BitsLength()) { 1094 iconBits[i++] = B_TRANSPARENT_32_BIT.red; 1095 iconBits[i++] = B_TRANSPARENT_32_BIT.green; 1096 iconBits[i++] = B_TRANSPARENT_32_BIT.blue; 1097 iconBits[i++] = B_TRANSPARENT_32_BIT.alpha; 1098 } 1099 } else { 1100 // Assume B_CMAP8 1101 for (int32 i = 0; i < icon->BitsLength(); i++) 1102 iconBits[i] = B_TRANSPARENT_MAGIC_CMAP8; 1103 } 1104 1105 barInfo->iconCache[index] = barInfo->icon = icon; 1106 1107 return B_OK; 1108 } 1109 1110 1111 status_t 1112 TBarApp::_CacheWindowIcon(WindowIconCache* winCache) 1113 { 1114 if (winCache == NULL) 1115 return B_BAD_VALUE; 1116 1117 // clip font size 1118 int32 fontSize = (int32)floorf(be_plain_font->Size()); 1119 if (fontSize < kMinimumFontSize) 1120 fontSize = kMinimumFontSize; 1121 if (fontSize > kMaximumFontSize) 1122 fontSize = kMaximumFontSize; 1123 1124 // icon index based on font size 1125 const int32 index = (fontSize - kMinimumFontSize) / kFontSizeInterval; 1126 1127 // first look in the icon cache 1128 winCache->icon = winCache->iconCache[index]; 1129 if (winCache->icon != NULL) 1130 return B_OK; 1131 1132 int32 id = winCache->id; 1133 uint8* data; 1134 size_t size; 1135 1136 // icon wasn't in cache, get vector icon from resource and cache it 1137 data = (uint8*)AppResSet()->FindResource(B_VECTOR_ICON_TYPE, id, &size); 1138 if (data != NULL && size > 0) { 1139 // seems valid, scale bitmap according to font size 1140 BBitmap* icon = new(std::nothrow) BBitmap( 1141 BRect(B_ORIGIN, be_control_look->ComposeIconSize(B_MINI_ICON)), 1142 B_RGBA32); 1143 if (icon != NULL && icon->InitCheck() == B_OK 1144 && BIconUtils::GetVectorIcon(const_cast<const uint8*>(data), 1145 size, icon) == B_OK) { 1146 winCache->iconCache[index] = winCache->icon = icon; 1147 1148 return B_OK; 1149 } else if (icon != NULL) { 1150 // ran out of memory allocating bitmap, this should never happen 1151 delete icon; 1152 delete winCache->iconCache[index]; 1153 winCache->iconCache[index] = winCache->icon = NULL; 1154 1155 return B_NO_MEMORY; 1156 } 1157 } 1158 1159 return B_ERROR; 1160 } 1161 1162 1163 // #pragma mark - BarTeamInfo 1164 1165 1166 BarTeamInfo::BarTeamInfo(BList* teams, uint32 flags, char* sig, char* name, 1167 BBitmap* icon) 1168 : 1169 teams(teams), 1170 flags(flags), 1171 sig(sig), 1172 name(name), 1173 icon(icon) 1174 { 1175 _Init(); 1176 } 1177 1178 1179 BarTeamInfo::BarTeamInfo(const BarTeamInfo &info) 1180 : 1181 teams(new BList(*info.teams)), 1182 flags(info.flags), 1183 sig(strdup(info.sig)), 1184 name(strdup(info.name)), 1185 icon(new BBitmap(*info.icon)) 1186 { 1187 _Init(); 1188 } 1189 1190 1191 BarTeamInfo::~BarTeamInfo() 1192 { 1193 delete teams; 1194 free(sig); 1195 free(name); 1196 for (int32 i = 0; i < kIconCacheCount; i++) 1197 delete iconCache[i]; 1198 } 1199 1200 1201 void 1202 BarTeamInfo::_Init() 1203 { 1204 for (int32 i = 0; i < kIconCacheCount; i++) 1205 iconCache[i] = NULL; 1206 } 1207 1208 1209 // #pragma mark - WindowIconCache 1210 1211 1212 WindowIconCache::WindowIconCache(int32 id, BBitmap* icon) 1213 : 1214 id(id), 1215 icon(icon) 1216 { 1217 _Init(); 1218 } 1219 1220 1221 WindowIconCache::WindowIconCache(const WindowIconCache &cache) 1222 : 1223 id(cache.id), 1224 icon(new BBitmap(*cache.icon)) 1225 { 1226 _Init(); 1227 } 1228 1229 1230 WindowIconCache::~WindowIconCache() 1231 { 1232 for (int32 i = 0; i < kWindowIconCacheCount; i++) 1233 delete iconCache[i]; 1234 } 1235 1236 1237 void 1238 WindowIconCache::_Init() 1239 { 1240 for (int32 i = 0; i < kWindowIconCacheCount; i++) 1241 iconCache[i] = NULL; 1242 } 1243