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